shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。
spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。
shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。
使用shiro实现系统 的权限管理,有效提高开发效率,从而降低开发成本。
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。
authenticator:认证器,主体进行认证最终通过authenticator进行的。
authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。
SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。
比如 md5散列算法。
pom.xml
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- shiro加入注解时要加入的包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<!-- shiro缓存 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 缓存ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
//spring boot Realm 用于认证和授权
@Component
public class CustomRealm extends AuthorizingRealm {
//注入service
@Autowired
UserService userService;
@Override
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
String password = userService.queryPasswordByName(username);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, "customRealm");
return info;
}
@Override
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//根据认证传进来的user信息 查询该user所对应的perms信息
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
List<String> perms = userService.queryPermsByName(primaryPrincipal);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(perms);
return info;
}
}
//spring boot Configuration Shiro配置
@Configuration
public class ShiroConfig {
/*注册realm 注册sessionManager*/
/*注册cacheManager*/
@Bean
public SecurityManager securityManager(CustomRealm customRealm,
DefaultWebSessionManager sessionManager,
EhCacheManager ehCacheManager){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(customRealm);
defaultWebSecurityManager.setSessionManager(sessionManager);
defaultWebSecurityManager.setCacheManager(ehCacheManager);
return defaultWebSecurityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuthor");
HashMap<String, String> filterMap = new HashMap<>();
filterMap.put("/unAuthor","anon");
filterMap.put("/login","anon");
filterMap.put("/refuse","anon");
//filterMap.put("/admin/user/*","perms[user:query]");
filterMap.put("/logout","logout");
filterMap.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
//加入注解的方式
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
//失败页面
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
properties.setProperty("org.apache.shiro.authz.UnauthorizedException","/refuse");
simpleMappingExceptionResolver.setExceptionMappings(properties);
return simpleMappingExceptionResolver;
}
/*session Manager*/
@Bean
public DefaultWebSessionManager defaultWebSessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(60000);
sessionManager.setDeleteInvalidSessions(true);
return sessionManager;
}
/*注册cacheManager*/
@Bean
public EhCacheManager ehCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:shiro-cache.xml");
return ehCacheManager;
}
}
//shiro-cache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!--diskStore:缓存数据持久化的目录 地址 -->
<diskStore path="E:\develop\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
diskPersistent="false"
timeToIdleSeconds="10"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
//controller
@RequestMapping("login")
public String login(String username,String password){
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
}catch (Exception i){
return "login";
}
return "success";
}
/*简单说明
<defaultCache
maxElementsInMemory="10000"
内存中缓存的最大的对象条目
eternal="false"
是否放在磁盘
timeToIdleSeconds="120
对象的空闲时间 单位是s 超时即从内存去掉
timeToLiveSeconds="120"
对象的生存周期 单位是s 2min
overflowToDisk="true"
内存中超过上限之后否放在磁盘中
maxElementsOnDisk="10000000"
disk中最多保存多少个对象
diskPersistent="false"
jvm 终止的时候是否保存到磁盘中
diskExpiryThreadIntervalSeconds="120"
120s 轮询一次,去清除过期的对象
memoryStoreEvictionPolicy="LRU"
内存清除策略:LRU 把某些cache干掉
Least Recently Used 算法 最近最少使用算法
去最近的一段时间内最不经常使用的那些对象。
LFU least Frequency Used 最不经常使用
使用频率最小的那些对象
FIFO fisrt in first out 队列 />
- /*RequiresAuthentication:
使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证。
- RequiresGuest:
使用该注解标注的类,实例,方法在访问或调用时,当前Subject可以是“gust”身份,不需要经过认证或者在原先的session中存在记录。
- RequiresPermissions:
当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法。如果当前Subject不具有这样的权限,则方法不会被执行。
- RequiresRoles:
当前Subject必须拥有所有指定的角色时,才能访问被该注解标注的方法。如果当天Subject不同时拥有所有指定角色,则方法不会执行还会抛出AuthorizationException异常。
- RequiresUser
当前Subject必须是应用的用户,才能访问或调用被该注解标注的类,实例,方法。
注意:
Shiro的认证注解处理是有内定的处理顺序的,如果有个多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):
*/