一、缓存
1.添加依赖
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
2.配置文件
#Redis服务器地址
spring.redis.host=localhost
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码
#spring.redis.password=foobared
#连接池最大连接数
spring.redis.lettuce.pool.max-active=8
#连接池最大阻塞等待时间
spring.redis.lettuce.pool.max-wait=-1
#连接池最大空闲连接
spring.redis.lettuce.pool.max-idle=8
#连接池最小空闲连接
spring.redis.lettuce.pool.min-idle=0
#Redis服务器超时时间
spring.redis.timeout=5000
3.改造ShiroConfig
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm shiroRealm = new MyShiroRealm();
//设置启用缓存
shiroRealm.setCachingEnabled(true);
shiroRealm.setAuthorizationCachingEnabled(true);
shiroRealm.setAuthorizationCacheName("authorizationCache");
//设置凭证
shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return shiroRealm;
}
@Bean
public SecurityManager securityManager(){
//安全管理器
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//注入Realm
securityManager.setRealm(myShiroRealm());
//注入缓存管理器
securityManager.setCacheManager(cacheManager());
//注入会话管理器
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
//Shiro过滤器
ShiroFilterFactoryBean shiroFilterFactory = new ShiroFilterFactoryBean();
//注入SecurityManager
shiroFilterFactory.setSecurityManager(securityManager);
//权限验证:使用Filter控制资源(URL)的访问
shiroFilterFactory.setLoginUrl("/dologin");
shiroFilterFactory.setSuccessUrl("/main");
shiroFilterFactory.setUnauthorizedUrl("/403");//没有权限跳转
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
filterChainDefinitionMap.put("/css/**","anon");
filterChainDefinitionMap.put("/fonts/**","anon");
filterChainDefinitionMap.put("/images/**","anon");
filterChainDefinitionMap.put("/js/**","anon");
filterChainDefinitionMap.put("/localcss/**","anon");
filterChainDefinitionMap.put("/localjs/**","anon");
filterChainDefinitionMap.put("/login","anon");
filterChainDefinitionMap.put("/logout","logout");//注销过滤器
//配置需要特定权限才能访问的资源
// filterChainDefinitionMap.put("/user/list","perms[用户列表]");
// filterChainDefinitionMap.put("/user/add","perms[用户添加]");
// filterChainDefinitionMap.put("/user/edit","perms[用户编辑]");
// filterChainDefinitionMap.put("/user/del","perms[用户删除]");
//动态授权
List<SysRight> rights = roleService.findAllRights();
for (SysRight right :rights){
if (right.getRightUrl()!=null && !right.getRightUrl().trim().equals("")){
filterChainDefinitionMap.put(right.getRightUrl(),"perms["+right.getRightCode()+"]");
}
}
//配置认证访问
filterChainDefinitionMap.put("/**","authc");//必须放在过滤器的最后面
shiroFilterFactory.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactory;
}
4.测试
它会报User转换错误别慌! 添加一个热部署包来提高效率先!!!
完成后再Redis中查看信息如下:
二、加密
1.测试
加上"盐"试试
@Test
public void testMd5Hash(){
String password = "admin";
String salt = "czkt";
Md5Hash md5Hash = new Md5Hash(password,salt,1);
System.out.println(md5Hash.toString());
//输出36aa3e095a86925b7658b5d00557fa77
}
2.加密和验证
设俩个接口:
public interface PasswordService {
String encryptPassword(Object plaintextPassword) throws IllegalArgumentException;
}
public interface CredentialsMatcher {
boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);
}
3.具体实现
1.在Service添加加密方法:
@Override
public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException {
Md5Hash md5Hash = new Md5Hash(plaintextPassword,"",1);
String mdPass=md5Hash.toString();
Md5Hash md5 = new Md5Hash(plaintextPassword,mdPass.toString(),2);
return md5Hash.toString();
}
2.在ShiroConfig中注入MyShiroRealm
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//使用md5算法进行加密
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//设置散列次数
hashedCredentialsMatcher.setHashIterations(1);
return hashedCredentialsMatcher;
}
3.修改返回身份信息的代码
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("调用MyShiroRealm.doGetAuthenticaticationInfo 获取身份信息!");
//获取身份信息
UsernamePasswordToken token =(UsernamePasswordToken)authenticationToken;
String usrName = token.getUsername();
//每次访问,登录次数加1
ValueOperations<String,String> operations = stringRedisTemplate.opsForValue();
operations.increment(SHIRO_LOGIN_COUNT+usrName,1);
//计数大于5时设置用户被锁定一小时,清空登录计数
if (Integer.parseInt(operations.get(SHIRO_LOGIN_COUNT+usrName))>5){
operations.set(SHIRO_IS_LOCK+usrName,"LOCK");
stringRedisTemplate.expire(SHIRO_IS_LOCK+usrName,1, TimeUnit.HOURS);
stringRedisTemplate.delete(SHIRO_LOGIN_COUNT+usrName);//清空登录计数
}
if ("LOCK".equals(operations.get(SHIRO_IS_LOCK+usrName))){
throw new DisabledAccountException();
}
User user = userService.getUserByUserName(usrName);
if (user==null){
throw new UnknownAccountException();//账号错误
}
if (user.getUsrFlag()==null || user.getUsrFlag().intValue()==0){
throw new LockedAccountException();//账号锁定
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getUsrPassword(), ByteSource.Util.bytes("czkt"),getName());
return info;
}
**这样我们在去测试看看就好了!我们下次见~**