概述

上面说到Spring Security,其实还有一个常用权限框架Apache Shiro,主要有如下功能:

  1. Apache Shiro是一个功能丰富且灵活的Java安全框架,提供了身份认证、授权、加密、会话管理等功能。
  2. Shiro的设计理念是简单直观,易于使用和集成到各种类型的应用程序中。
  3. Shiro不依赖于其他框架,可以与任何Java应用程序一起使用,包括Spring应用程序。
  4. Shiro的安全功能可以轻松地集成到Java应用程序的各个层次,包括Web应用程序、RESTful服务、命令行应用程序等。

应用

具体使用过程如下:

引用pom依赖

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.6.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.7.0</version>
		</dependency>

配置用户授权规则

@Slf4j
@Component
public class UserRealm extends AuthorizingRealm{

    @Autowired
    SysUserService sysUserService;

    @Autowired
    SysResourceService sysResourceService;

    /**
     * 用户授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 获取用户所有的权限标识。        simpleAuthorizationInfo.setStringPermissions(sysResourceService.selectUserPerms(ShiroUtil.getUserId()));
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;

        SysUser sysUser = sysUserService.findByAccount(token.getUsername());
        if(sysUser == null){
            log.error(REnum.UNkNOWN_ACCOUNT.getMessage()+"SysUser = {}"+sysUser);
            throw new UnknownAccountException();
        }
        if(ForbiddenEnum.DISABLE.getCode().toString().equals(sysUser.getForbidden())){
            log.error(REnum.UNkNOWN_ACCOUNT.getMessage()+"SysUser = {}"+sysUser);
            throw new DisabledAccountException();
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(sysUser,sysUser.getPassword(),getName());
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(sysUser.getSalt()));
        return simpleAuthenticationInfo;
    }

    /**
     * 密码验证服务
     * @param credentialsMatcher
     */
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher md5HashedCredentialsMatcher = new HashedCredentialsMatcher();
        md5HashedCredentialsMatcher.setHashAlgorithmName(ShiroUtil.hashAlgorithmName);
        md5HashedCredentialsMatcher.setHashIterations(ShiroUtil.hashIterations);
        md5HashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        super.setCredentialsMatcher(md5HashedCredentialsMatcher);
    }
}

对Shiro进行配置


@Configuration
public class ShiroConfig {

    @Bean("sessionManager")
    public SessionManager sessionManager(){

        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //设置session过期时间为1小时
        sessionManager.setGlobalSessionTimeout(60 * 60 * 1000);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    @Bean("securityManager")
    public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/anno/notLogin");
        shiroFilter.setUnauthorizedUrl("/");

        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/sys/**", "authc");
        filterMap.put("/anno/**", "anon");
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

具体接口使用,sys:role:detail 对应用户表中配置的角色标识,用户登录后缓存所有用户权限表示,用户访问具体接口的时候匹配到接口上面权限标识,则正常访问,否则禁止访问。如:

    /**
     * 查询订单详情
     * @param id
     * @return
     */
    @RequiresPermissions("sys:role:detail")
    @GetMapping("/selectRoleDetail")
    public R selectRoleDetail(@RequestParam(value = "id",required = false) Integer id){

        Assert.isNull(id,"id不能为空");
        return sysRoleService.selectRoleDetail(id);

    }

Apache Shiro 和spring Security 对比

Apache Shiro:

优势:

  1. 简单直观:Shiro的设计理念是简单易用,它提供了直观的API和配置选项,使得开发人员可以快速上手并集成到应用程序中。
  2. 轻量级:Shiro是一个轻量级的框架,不依赖于其他框架,可以与任何Java应用程序一起使用,而不增加过多的额外依赖。
  3. 灵活性:Shiro提供了丰富的扩展点和定制选项,可以根据需要定制各种安全功能,例如自定义身份认证、授权策略等。

劣势:

  1. 功能相对较少:相对于Spring Security,Shiro提供的功能相对较少,特别是在与Spring框架集成、与第三方认证服务集成等方面可能稍显不足。
  2. 社区和生态系统相对较小:虽然Shiro有一定的用户群体和社区支持,但与Spring Security相比,其生态系统相对较小,可能会导致在某些情况下找不到足够的支持和解决方案。

Spring Security:

优势:

  1. 与Spring框架紧密集成:Spring Security是Spring框架的一部分,与Spring的依赖注入、AOP等特性紧密集成,使得在Spring应用程序中使用Spring Security变得非常方便。
  2. 功能丰富:Spring Security提供了丰富的安全功能,包括身份认证、授权、攻击防护等方面的功能,并且提供了大量的扩展点和配置选项,可以满足各种复杂场景下的安全需求。
  3. 强大的社区支持和生态系统:Spring Security拥有庞大的用户群体和活跃的社区支持,有大量的文档、教程和解决方案可供参考,同时也有丰富的第三方库和插件可供使用。

劣势:

  1. 学习曲线较陡:由于Spring Security提供了非常丰富的功能和选项,因此学习曲线可能会相对较陡,对于新手来说可能需要花费一些时间来掌握。
  2. 配置相对繁琐:与Shiro相比,Spring Security的配置可能相对繁琐一些,特别是在一些复杂的场景下可能需要编写大量的配置代码。