首页 > 编程知识 正文

session和cookie的用法,使用cookie和session实现登录

时间:2023-05-05 22:14:08 阅读:285642 作者:3425

1 背景

作为“自学成才”的野路子程序员,一直忙于CRUD,没有系统地学习CS基础知识,导致面试的时候屡屡被CS专业的同学diss,于是乎知耻而后勇,认认真真地补习基础知识,这篇博客就来学习、总结下啥是Cookie、啥是Session。

以前看过面试宝典,只知道Cookie是保存在客户端、Session保存在服务端,除此之外一无所知,直到昨天晚上躺在床上辗转反侧、思绪万千,看了一篇关于单点登录的博客,才恍然大悟:这俩玩意是用来校验用户登录状态的。因为http是无状态的,所以客户端每次向服务端发起请求的时候,服务端是不认识客户端的(服务端:我这个人脸盲,就是说分不清谁漂亮谁不漂亮),那么为了搞清楚用户是否已登录,就要有一种机制来分辨不同的客户端。

区别:Session是服务端的东西,用户是看不到的;Cookie是客户端的东西,用户能看得到,但是不能跨域请求。

客户端第一次访问服务端时,服务端会生成一个sessionId并返回给客户端,客户端给保存到cookie中,按下F12打开开发者模式,看到请求头:Cookie:JSESSIONID=xxxxxxxxxxxxxxxxxxx  这一串就是服务端为请求生成的sessionId。

本文用到的代码已经托管在github上了:

(1)登录校验

https://github.com/hfutlilong/test/blob/master/src/main/java/filter/LoginFilter.java

https://github.com/hfutlilong/test/blob/master/src/main/java/controller/LoginController.java

https://github.com/hfutlilong/test/blob/master/src/main/java/controller/MainController.java

(2)各种JSP页面

https://github.com/hfutlilong/test/tree/master/web/WEB-INF/views

2 用Session校验用户登录状态 2.1 登录状态验证

我们通过在session中设置属性“isLogin”来标识登录状态,登录的时候置为true、退出的时候置为false,是不是很神奇,请叫我的全名——达文西。

用Filter过滤器来校验用户登录状态。过滤器是Servlet的,拦截器是Spring的,优先级的话过滤器要高于拦截器。

很简单,我们实现Filter接口,重写doFilter()方法:

package filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;public class LoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(); String uri = req.getRequestURI(); boolean isLoginReq = uri.matches("/user/.*\.do"); boolean isLogin = session.getAttribute("isLogin") != null && (boolean)session.getAttribute("isLogin"); if (isLoginReq || isLogin) { chain.doFilter(request, response); return; } //跳转至登录页面 res.sendRedirect("/user/login.do"); }}

然后配置在web.xml中:

<filter> <filter-name>loginFilter</filter-name> <filter-class>filter.LoginFilter</filter-class></filter><filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping> 2.2 登录与退出

写一个处理登录、退出的Controler:
 

@Controller@RequestMapping("/user")public class LoginController { @Autowired private UserLoginService userLoginService; @RequestMapping("/login") public String login() { return "login"; } @RequestMapping("/loginAction") public String loginAction(String username, String password, HttpServletRequest request, HttpServletResponse response) { UserLoginVO userLoginVO = userLoginService.queryUserByNamePwd(username, password); if (userLoginVO != null) { request.getSession().setAttribute("isLogin", true); return "welcome"; } return "login"; } @RequestMapping("/logout") public void logout(HttpServletRequest request, HttpServletResponse response) { request.getSession().removeAttribute("username"); try { request.getSession().setAttribute("isLogin", false); response.sendRedirect("/user/login.do"); } catch (IOException e) { e.printStackTrace(); } }}

 

2.3 业务代码

好吧,其实就是hello world:

@Controller@RequestMappingpublic class MainController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello(){ return "hello"; }} 2.4 JSP页面

不要问我为什么还在用JSP,因为我只是个后端小码仔,不会写前端,就会一点点JSP。。。嗯,真香

登录页面长这样子:

3 用Cookie校验用户状态

session保存在Map结构的内存中,默认的过期时间是30分种,那像有些网站可能关闭之后、过了几天再去打开也仍然不需要登录,这种其实就是用Cookie校验了,不然的话内存会撑爆的。

实现方式:在Cookie中增加"username"属性,如果访问的请求中,cookie包含该属性,那就认为是登录状态。

与上面类似,也是实现一个Filter接口、登录时保存Cookie、退出时清除Cookie,但是Cookie没有删除方法,所以需要设置Cookie有效期为0秒,即可删除。

3.1 过滤器:根据Cookie判断是否已登录 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String uri = req.getRequestURI(); boolean isLoginReq = uri.matches("/user/.*\.do"); boolean isLogin = false; // 判断cookie是否有username,如果有代表登陆过 Cookie[] cookies = req.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (cookie != null && URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { isLogin = true; break; } } } if (isLoginReq || isLogin) { chain.doFilter(request, response); return; } //跳转至登录页面 res.sendRedirect("/user/login.do");} 3.2 登录与退出

实验中我们设置Cookie过期时间为60s,那么在登录后的1分钟内是可以正常执行业务接口的,但是超过了1分钟就要重新登录。

@Controller@RequestMapping("/user")public class LoginController { @Autowired private UserLoginService userLoginService; @RequestMapping("/login") public String login() { return "login"; } @RequestMapping("/loginAction") public String loginAction(String username, String password, HttpServletRequest request, HttpServletResponse response) { UserLoginVO userLoginVO = userLoginService.queryUserByNamePwd(username, password); if (userLoginVO != null) { // 把用户名保存在Cookie里 Cookie cookie = new Cookie("username", username); cookie.setMaxAge(60); // 单位:秒 cookie.setPath("/"); response.addCookie(cookie); return "welcome"; } return "login"; } @RequestMapping("/logout") public void logout(HttpServletRequest request, HttpServletResponse response) { request.getSession().removeAttribute("username"); try { //把过期时间设置成0秒,表示删除该属性 Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { System.out.println(URLDecoder.decode(cookie.getName(), "utf-8")); if (URLDecoder.decode(cookie.getName(), "utf-8").equals("username")) { cookie.setMaxAge(0); // 删除cookie cookie.setPath("/"); response.addCookie(cookie); } } } response.sendRedirect("/user/login.do"); } catch (IOException e) { e.printStackTrace(); } }}

登录后可以看到cookie中新增了username:

4 总结 session和cookie的作用:判断登录状态;session保存在服务端,用户不可见,有效期可设置,默认30分钟;cookie保存在客户端,用户可以看到;session的生命周期是一个会话(从打开浏览器到关闭浏览器),cookie的生命周期根据设置的过期时间值,如果没设置过期时间,则不会保存在本地,在关闭浏览器后即失效。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。