如标题有如下两个功能实现:
记住我的功能:通过设置key为“rememberMe”的cookie保存在客户端来完成记住我的功能,下次用户访问指定页面时就不会重新登录,一直到cookie过期后才会重新登录。
个人博客:http://z77z.oschina.io/
此项目下载地址:https://git.oschina.net/z77z/springboot_mybatisplus
在ShiroConfig.java中添加如下方法:
/**
* cookie对象;
* @return
*/
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//
simpleCookie.setMaxAge(2592000);
return simpleCookie;
}
/**
* cookie管理对象;记住我功能
* @return
*/
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cookie的有效时间等等。
rememberMeManager()方法是生成rememberMe管理器,而且要将这个rememberMe管理器设置到securityManager中,如下:
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myShiroRealm());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(SessionManager());
//注入记住我管理器;
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
其实上面的步骤,也就是rememberMe管理器可以不用配置,shiro会使用默认的配置,之所以要配置的目的是为了能够在实际业务环境中自定义其中的参数。
@RequestMapping(value="ajaxLogin",method=RequestMethod.POST)
@ResponseBody
public Map submitLogin(String username, String password,Boolean rememberMe,Model model) {
Map resultMap = new LinkedHashMap();
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);
SecurityUtils.getSubject().login(token);
resultMap.put("status", 200);
resultMap.put("message", "登录成功");
} catch (Exception e) {
resultMap.put("status", 500);
resultMap.put("message", e.getMessage());
}
return resultMap;
}
之前我是将shiro已经实现的UsernamePasswordToken类再封装了一层,最后发现没有必要,直接使用shiro提供的UsernamePasswordToken的类,其中有一个构造函数需要传rememberMe这个参数,也就是shiro为我们已经实现好了,推荐大家去看下UsernamePasswordToken这个类的源码。
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript"
src="<%=basePath%>/static/js/jquery-1.11.3.js">script>
<title>登录title>
head>
<body>
错误信息:
<h4 id="erro">h4>
<form>
<p>
账号:<input type="text" name="username" id="username" value="admin" />
p>
<p>
密码:<input type="text" name="password" id="password" value="123" />
p>
<P><input type="checkbox" name="rememberMe" id="rememberMe" />记住我P>
<p>
<input type="button" id="ajaxLogin" value="登录" />
p>
form>
body>
<script>
$(function(){
$("#ajaxLogin").click(function() {
var username = $("#username").val();
var password = $("#password").val();
var rememberMe =$('#rememberMe').is(':checked');
$.post("/ajaxLogin", {
"username" : username,
"password" : password,
"rememberMe" : rememberMe
}, function(result) {
if (result.status == 200) {
location.href = "/index";
} else {
$("#erro").html(result.message);
}
});
});
});
script>
html>
添加一个记住我的单选框,来控制是否需要记住我。
因为getGifCode是获取验证码的链接,所以要配置为anon,不需要权限验证。user权限是配置记住我或认证通过可以访问,所以将/**链接设置为user权限,就可以实现记住我的功能。
注意权限添加的排序。
/**
* 获取验证码(Gif版本)
* @param response
*/
@RequestMapping(value="getGifCode",method=RequestMethod.GET)
public void getGifCode(HttpServletResponse response,HttpServletRequest request){
try {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/gif");
/**
* gif格式动画验证码
* 宽,高,位数。
*/
Captcha captcha = new GifCaptcha(146,33,4);
//输出
captcha.out(response.getOutputStream());
HttpSession session = request.getSession(true);
//存入Session
session.setAttribute("_code",captcha.text().toLowerCase());
} catch (Exception e) {
System.err.println("获取验证码异常:"+e.getMessage());
}
}
生成验证码后,将图片返回到页面,将字符串保存在当前会话的session域中。
这个GIF验证码的生成插件源码在我的项目io.z77z.vcode这个包下面,大家需要的话可以在我的码云上去下载。
/**
* ajax登录请求
* @param username
* @param password
* @return
*/
@RequestMapping(value="ajaxLogin",method=RequestMethod.POST)
@ResponseBody
public Map submitLogin(String username, String password,String vcode,Boolean rememberMe,Model model) {
Map resultMap = new LinkedHashMap();
if(vcode==null||vcode==""){
resultMap.put("status", 500);
resultMap.put("message", "验证码不能为空!");
return resultMap;
}
Session session = SecurityUtils.getSubject().getSession();
//转化成小写字母
vcode = vcode.toLowerCase();
String v = (String) session.getAttribute("_code");
//还可以读取一次后把验证码清空,这样每次登录都必须获取验证码
//session.removeAttribute("_come");
if(!vcode.equals(v)){
resultMap.put("status", 500);
resultMap.put("message", "验证码错误!");
return resultMap;
}
try {
UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);
SecurityUtils.getSubject().login(token);
resultMap.put("status", 200);
resultMap.put("message", "登录成功");
} catch (Exception e) {
resultMap.put("status", 500);
resultMap.put("message", e.getMessage());
}
return resultMap;
}
登录的时候判断前台传入的验证码和session中的是否一致。
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript"
src="<%=basePath%>/static/js/jquery-1.11.3.js">script>
<title>登录title>
head>
<body>
错误信息:
<h4 id="erro">h4>
<form>
<p>
账号:<input type="text" name="username" id="username" value="admin" />
p>
<p>
密码:<input type="text" name="password" id="password" value="123" />
p>
<p>
验证码:<input type="text" name="vcode" id="vcode"/>
p>
<p>
<img alt="验证码" src="/getGifCode">
p>
<P><input type="checkbox" name="rememberMe" id="rememberMe" />记住我P>
<p>
<input type="button" id="ajaxLogin" value="登录" />
p>
form>
body>
<script>
$(function(){
$("#ajaxLogin").click(function() {
var username = $("#username").val();
var password = $("#password").val();
var vcode = $("#vcode").val();
var rememberMe =$('#rememberMe').is(':checked');
$.post("/ajaxLogin", {
"username" : username,
"password" : password,
"vcode" : vcode,
"rememberMe" : rememberMe
}, function(result) {
if (result.status == 200) {
location.href = "/index";
} else {
$("#erro").html(result.message);
}
});
});
});
script>
html>
到此,我们集成shiro和redis,学习了一下功能的实现:
香蕉硬币点赞走一波啦。。。。。。