概述
上面说到Spring Security,其实还有一个常用权限框架Apache Shiro,主要有如下功能:
- Apache Shiro是一个功能丰富且灵活的Java安全框架,提供了身份认证、授权、加密、会话管理等功能。
- Shiro的设计理念是简单直观,易于使用和集成到各种类型的应用程序中。
- Shiro不依赖于其他框架,可以与任何Java应用程序一起使用,包括Spring应用程序。
- 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:
优势:
- 简单直观:Shiro的设计理念是简单易用,它提供了直观的API和配置选项,使得开发人员可以快速上手并集成到应用程序中。
- 轻量级:Shiro是一个轻量级的框架,不依赖于其他框架,可以与任何Java应用程序一起使用,而不增加过多的额外依赖。
- 灵活性:Shiro提供了丰富的扩展点和定制选项,可以根据需要定制各种安全功能,例如自定义身份认证、授权策略等。
劣势:
- 功能相对较少:相对于Spring Security,Shiro提供的功能相对较少,特别是在与Spring框架集成、与第三方认证服务集成等方面可能稍显不足。
- 社区和生态系统相对较小:虽然Shiro有一定的用户群体和社区支持,但与Spring Security相比,其生态系统相对较小,可能会导致在某些情况下找不到足够的支持和解决方案。
Spring Security:
优势:
- 与Spring框架紧密集成:Spring Security是Spring框架的一部分,与Spring的依赖注入、AOP等特性紧密集成,使得在Spring应用程序中使用Spring Security变得非常方便。
- 功能丰富:Spring Security提供了丰富的安全功能,包括身份认证、授权、攻击防护等方面的功能,并且提供了大量的扩展点和配置选项,可以满足各种复杂场景下的安全需求。
- 强大的社区支持和生态系统:Spring Security拥有庞大的用户群体和活跃的社区支持,有大量的文档、教程和解决方案可供参考,同时也有丰富的第三方库和插件可供使用。
劣势:
- 学习曲线较陡:由于Spring Security提供了非常丰富的功能和选项,因此学习曲线可能会相对较陡,对于新手来说可能需要花费一些时间来掌握。
- 配置相对繁琐:与Shiro相比,Spring Security的配置可能相对繁琐一些,特别是在一些复杂的场景下可能需要编写大量的配置代码。