学习了一天左右的cookie和session,用自己的理解写了个简单的登录
学习过程中遇到的问题:
- cookie中的JSESSIONID,暂时不懂作用
- 前端用ajax请求成功后使用location.replace方法跳转界面,能够成功跳转却无法阻止浏览器后退按钮(未解决)
- 使用cookie登录但没有session,导致被拦截器拦截登录请求(已解决)
- 用户登录成功后使用浏览器后退按钮或url回到登录页面导致重复登录(目前只能做到使用拦截器阻止用户通过url进入登录页面)
- 暂时还没想起其它,想到后在补充
- 不知道这样写会不会有什么问题,错误或不足之处还请指正。
下面是代码:
前端ajax提交登录表单
function login(){
var username = $("#username").val();
var password = $("#password").val();
var autologin = $("#autologin").is(':checked');
$.ajax({
type:"post",
url:"/tomain",
data: {
username: username,
password: password,
autologin: autologin
},
success:function (page) {
location.href="http://localhost:8080/"+page;
}
});
}
提交表单的方法
/*
* 三个值分别表示账号、密码、是否勾选记住密码
*/
@RequestMapping("/tomain")
@ResponseBody
public String tomain(
@RequestParam("username") String username,
@RequestParam("password") String password,
@RequestParam("autologin") boolean autologin,
HttpServletRequest request,
HttpServletResponse response){
Cookie[] cookies = request.getCookies();
//cookies为空表示上次登录时没有选择自动登录或第一次登录
if (cookies == null){
//如果账号密码匹配
if (username != null && !username.equals("") && password.equals("123456")){
//取到session值,没有则创建
HttpSession session = request.getSession();
session.setAttribute("logOn",username);
//设置最大存活时间,单位为秒
session.setMaxInactiveInterval(60*10);
//将账号密码存入cookie,在实际开发中账号密码需要先进行加密
Cookie cookie = new Cookie("autoLogin",username+"#"+password);
/*
* 如果用户勾选了自动登录
* 就给cookie一个存活时间
* 这样就不会随着浏览器的关闭而清除cookie
* 否则就不设置,这样当用户关闭浏览器时就会清除cookie
* 下次登录仍然需要输入账号密码
*/
if (autologin){
System.out.println("自动登录,一个月后过期");
//设置最大年龄,即为cookie存活时间,单位为秒
cookie.setMaxAge(60*60*24*30);
cookie.setPath("/");
}
//把cookie发送给客户端,由客户端保存
response.addCookie(cookie);
System.out.println("登录成功");
return "main";
}else {
System.out.println("账号或密码错误");
return "login";
}
}else {
//有cookie则验证cookie中是否包含自动登录的账号密码
for (Cookie cookie : cookies) {
/*
* 考虑到cookie会保存一个月,而session只存在十分钟
* 为了防止用户携带cookie登录时被拦截器拦截
* 验证用户的登录session是否还在,不在则创建一个新的
*/
if(cookie.getName().equals("autoLogin")){
HttpSession session = request.getSession();
if(session.getAttribute("logOn") == null){
session.setAttribute("logOn",username);
session.setMaxInactiveInterval(60*10);
}
return "main";
}
}
System.out.println("没有选择自动登录");
return "login";
}
}
退出登录
@RequestMapping("/logout")
public String logout(HttpServletRequest request,HttpServletResponse response){
//退出登录时去掉登录session和自动登录cookie
request.getSession().removeAttribute("logOn");
Cookie autocookie = new Cookie("autoLogin",null);
autocookie.setMaxAge(0);
autocookie.setPath("/");
response.addCookie(autocookie);
//暂时不懂JSESSIONID的作用,退出登录时将它也处理掉
Cookie sessionid = new Cookie("JSESSIONID",null);
sessionid.setMaxAge(0);
sessionid.setPath("/");
response.addCookie(sessionid);
return "redirect:/login";
}
两个拦截器:
MainInterCeptor
public class MainInterCeptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/*
* 判断cookie和session是否都没有
* 都没有视为未登录,拒绝进入主页面
* 这里只能用&&使用||会导致页面在这里和LoginInterCeptor之间来回重定向
* 导致浏览器抛出localhost多次重定向从而拒绝服务
* 这只是给暂时的解决办法,更好的办法还没想到
*/
Cookie[] cookies = request.getCookies();
if(request.getSession().getAttribute("logOn") == null && cookies == null){
System.out.println("拦截请求");
response.sendRedirect("/login");
return false;
}else {
return true;
}
}
}
LoginInterCeptor
public class LoginInterCeptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Cookie[] cookies = request.getCookies();
//拦截登录页,当cookie有值时说明已经选择了自动登录或者已经登录,不允许进入登录页
if (cookies == null){
System.out.println("拦截器执行了,允许进入登录页");
return true;
}else {
System.out.println("拦截器执行了,拒绝进入登录页");
response.sendRedirect("/main");
return false;
}
}
}
mvc扩展配置
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加MainInterCeptor拦截器
registry.addInterceptor(new MainInterCeptor())
.addPathPatterns("/main")
.excludePathPatterns("/","/css/**","/fonts/**","/img/**","/js/**");
//添加LoginInterCeptor拦截器
registry.addInterceptor(new LoginInterCeptor())
.addPathPatterns("/login")
.excludePathPatterns("/","/css/**","/fonts/**","/img/**","/js/**");
}
}
开始找到一个能够阻止浏览器返回按钮的方法,经过几次代码修改之后失效了(这个方法没改,改的是自己写的代码),这里也放上来
window.location.hash="no-back";
window.location.hash="Again-No-back-button";
window.onhashchange=function(){
window.location.hash="no-back";
}
经过几次的修改,已经把这一天对cookie和session的理解都用上了,目前只能做到这里,下次再深入探究吧