参考demo地址:github
我的项目地址:github
注意:我的项目是
基于springboot2.x
shiro1.4.1
jwt
dubbo
zookeper
mybatisPlus3.x
mysql8.0
搭建的多模块项目
顺序 | 不足 | 解决方案 |
---|---|---|
1 | shiro不是盐值加密登录 | 盐值登录 |
2 | login接口需要权限才能访问 | shiroConfig添加免登录过滤 |
3 | 没有真正的角色和权限 ,只是单纯的模拟 | 添加数据库关于角色和权限的表 |
原本的代码
@PostMapping("/login")
public ResponseBean login(@RequestParam("username") String username,
@RequestParam("password") String password) {
UserBean userBean = userService.getUser(username);
if (userBean.getPassword().equals(password)) {
return new ResponseBean(200, "Login success", JWTUtil.sign(username, password));
} else {
throw new UnauthorizedException();
}
}
增加shiro盐值加密后的代码:
@PostMapping("/login")
public ResultInfo login(@RequestParam("username") String username,
@RequestParam("password") String password) {
SysUser userBean = userService.findUserInfo(username);
String encodePassword = ShiroKit.md5(password, password);
if (userBean.getPassWord().equals(encodePassword)) {
return new ResultInfo("200", "Login success", JWTUtil.sign(username, encodePassword));
} else {
throw new UnauthorizedException();
}
}
所用到的盐值加密的工具类,注意我的代码里面其实不存储盐值,用户名就是盐值,当然你也可以把盐值换一下
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import java.util.Random;
/**
* shiro工具类
*/
public class ShiroKit {
/**
* 加盐参数
*/
public final static String hashAlgorithmName = "MD5";
/**
* 循环次数
*/
public final static int hashIterations = 10;
/**
* shiro密码加密工具类
*
* @param credentials 密码
* @param saltSource 密码盐
* @return
*/
public static String md5(String credentials, String saltSource) {
ByteSource salt = new Md5Hash(saltSource);
return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations).toString();
}
public static void main(String[] args) {
System.out.println(md5("xiyou","xiyou"));
}
}
其实就是在下面的代码里添加一句即可
filterRuleMap.put("/login", "anon");
添加后变为:
@Bean("shiroFilter")
public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<>();
filterMap.put("jwt", new JWTFilter());
factoryBean.setFilters(filterMap);
factoryBean.setSecurityManager(securityManager);
factoryBean.setUnauthorizedUrl("/401");
/*
* 自定义url规则
* http://shiro.apache.org/web.html#urls-
*/
Map<String, String> filterRuleMap = new HashMap<>();
// 所有请求通过我们自己的JWT Filter
filterRuleMap.put("/**", "jwt");
// 访问401和404页面不通过我们的Filter
filterRuleMap.put("/401", "anon");
filterRuleMap.put("/login", "anon");
factoryBean.setFilterChainDefinitionMap(filterRuleMap);
return factoryBean;
}
Default value is “id”, that means your principal object has a method called “getId()”
解决方案: redisCacheManager.setPrincipalIdFieldName("userName");
如果你是用用户的name登录的话
String userName = (String) token.getPrincipal();
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
return redisManager;
}
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setPrincipalIdFieldName("userName");
return redisCacheManager;
}
/**
* lifecycleBeanPostProcessor是负责生命周期的 , 初始化和销毁的类
* (可选)
*/
@Bean("lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
因为默认的是JDK序列化乱码,虽然不影响使用,但乱码
shiro+redis的官网