历史文章
(一)Spring Boot 集成 Shiro 权限管理与密码加盐
主要完成功能
记住我功能:浏览器下次进入无需输入密码即可请求接口,但部分类似支付的接口还是需要跳转登录
配置SecurityManager 的 RememberMeManager
shiro 中的 "记住我" 功能是使用 Cookies 实现的,认证信息保存在浏览器上。
对于一些常规的增删改查操作的接口,可以让用户不用每次都输入密码进行登录,只有操作高危操作(如支付,修改密码,等核心重要业务时)才提示去登录。
首先修改 ShiroConfig
/**
* cookie对象
*
* @return
*/
public SimpleCookie rememberMeCookie() {
SimpleCookie cookie = new SimpleCookie("rememberMe");
// 设置cookie的过期时间,单位为秒,这里为一天
cookie.setMaxAge(86400);
return cookie;
}
/**
* cookie管理对象
*
* @return
*/
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
// rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位),通过以下代码可以获取
// KeyGenerator keygen = KeyGenerator.getInstance("AES");
// SecretKey deskey = keygen.generateKey();
// System.out.println(Base64.encodeToString(deskey.getEncoded()));
cookieRememberMeManager.setCipherKey(Base64.decode("vXP33AonIp9bFwGl7aT7rA=="));
return cookieRememberMeManager;
}
@Bean
SecurityManager securityManager() {
DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
defaultSecurityManager.setRealm(myRealm());
//添加 rememberMeManager
defaultSecurityManager.setRememberMeManager(rememberMeManager());
return defaultSecurityManager;
}
/**
* 修改
* map.put("/pay", "authc");//支付类需要安全校验的接口需要登录,不能使用记住我跳过
* map.put("/**", "user");//user指的是用户认证通过或者配置了Remember Me记住用户登录状态后可访问。
* //authc 指的是认证通过的用户
*/
@Bean
ShiroFilterFactoryBean filterFactoryBean(SecurityManager securityManager) {
//authc表示需要验证身份才能访问,还有一些比如anon表示不需要验证身份就能访问等。
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager);
bean.setLoginUrl("/login");
bean.setSuccessUrl("/index");
bean.setUnauthorizedUrl("/unauthorizedurl");
Map<String, String> map = new LinkedHashMap<>();
map.put("/doLogin", "anon");
map.put("/doRegister", "anon");
map.put("/pay", "authc");//支付类需要安全校验的接口需要登录,不能使用记住我跳过
map.put("/**", "user");//user指的是用户认证通过或者配置了Remember Me记住用户登录状态后可访问。
bean.setFilterChainDefinitionMap(map);
return bean;
}
修改登录接口
添加 rememberMe 参数,并设置到 UsernamePasswordToken 中
/**
* 登录接口
*
* @param username
* @param password
*/
@GetMapping("/doLogin")
public String doLogin(String username, String password, boolean rememberMe) {
Subject subject = SecurityUtils.getSubject();
if (!subject.isAuthenticated()) {
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
subject.login(token);
return "登录成功";
} catch (AuthenticationException e) {
e.printStackTrace();
return "登录失败";
}
} else {
return "已经登录成功";
}
}
写一个模拟支付的接口
不许用户直接以记住我的认证方式访问,必须通过用户名密码授权
@RestController
public class PayController {
@GetMapping("/pay")
public String pay() {
return "pay";
}
}
测试
使用浏览器登录 http://127.0.0.1:8080/doLogin?username=product&password=123456&rememberMe=true
然后关闭浏览器(要将浏览器完全杀掉),再打开浏览器,请求 addProduct 接口 http://127.0.0.1:8080/addProduct
提示 appProduct 代表访问成功,之后请求 http://127.0.0.1:8080/pay
提示 please login ,然后重新登录 http://127.0.0.1:8080/doLogin?username=product&password=123456&rememberMe=true,
再次请求 http://127.0.0.1:8080/pay ,提示 pay 代表请求成功