单体应用如何做用户登录验证及统一拦截(基于session+cookie的登录逻辑怎么做)

Posted 诺浅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单体应用如何做用户登录验证及统一拦截(基于session+cookie的登录逻辑怎么做)相关的知识,希望对你有一定的参考价值。

需求

我们知道单体应用登录验证模式为session+cookie的模式,该模式的原理为用户首次访问系统的时候,服务端会创建一个cookie返回给客户端,cookie中保存着JSESSIONID。以后的每次请求浏览器都会带上cookie中的信息给服务端,登录后的用户服务端会把用户信息保存至服务端的session中,通过JSESSIONID可以获取到保存至session中的信息。

交互时,服务端通过客户端提交的JSESSIONID获取到对应的session,然后判断session里面有没有用户信息,有就说明用户已登录,没有就需要跳转到登录页让用户登录。

需要注意的是sessionid并不是用户登录以后服务端才会返回的,而是用户首次访问网站时服务端返回的。服务端可以设置session的有效期,默认不设置30分钟,同时可以主动删除session,登出功能基于此实现。

那么该模式到底怎么落地呢?本文给出了一个落地的Demo,项目基于springboot+mybatis实现

登录逻辑

登录逻辑为

  1. 验证用户名是否存在
  2. 验证对应密码是否正确
  3. 如果用户名和密码正确则把用户的信息保存到session里面
/**
 * 用户登录逻辑
 *
 */
@RequestMapping("doLogin.do")
@ResponseBody
public ResultVo doLogin(String userName, String password) 
    ResultVo result = new ResultVo();
    try 
        if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) 
            userName = userName.trim();
            password = password.trim();
            // 根据账号获取用户信息
            UserEntity user = this.userService.getUserByUserName(userName);
            if (user != null) 
            	String encryPassword = Md5Util.str2Base32MD5(password);
            	// 比对密码
                if (encryPassword.equals(user.getPassword())) 
                 SessionUser sessionUser = new SessionUser();
                     sessionUser.setId(user.getId())
                             .setCode(user.getCode())
                             .setName(user.getName())
                             .setAccount(user.getUserName())
                             .setType(user.getTypeId())
                             .setDeparts(departs);

                     this.setSessionUser(sessionUser);
                     result.isSuccess(true);
                     result.setMsg("登录成功");
                else 
                   result.isSuccess(false);
                   result.setMsg("登录失败,密码错误");
               
           else 
               result.isSuccess(false);
               result.setMsg("登录失败,当前登录用户不存在");
           
	    
	catch (Exception e) 
        result.isSuccess(false);
        result.setMsg("登录失败");
        log.error("登录异常", e);
    


public void setSessionUser(SessionUser sessionUser) 
        //存储用户信息至会话
    setSession(USER, sessionUser);


/**
 * 设置session中的对象
 *
 * @param key
 * @param value
 */
public void setSession(String key, Object value) 
    if (!StringUtils.isEmpty(key) && value != null) 
        getSession().setAttribute(key, value);
    


@Autowired
private HttpServletRequest request;
/**
 * 获取HttpSession对象
 *
 * @return
 */
public HttpSession getSession() 
    return request.getSession();

全局拦截器逻辑

如果用户在没有登录状态下访问一个URL,则需要使用户跳转到登录页,也就是说用户请求任何一个URL都需要判断用户是否登录,拦截器很适合做这件事。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.dongbawen.config.IgnoreUrlPropertiesConfig;
import com.dongbawen.hppa.support.vo.SessionUser;
@Component
public class SessionInterceptor implements HandlerInterceptor 
 
	@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws  Exception
        String contextPath = request.getContextPath();
        Object session = request.getSession().getAttribute("USER");
        SessionUser sessionUser = null;
        if (session != null) 
            sessionUser = (SessionUser) session;
        
        if (sessionUser != null && StringUtils.isNotBlank(sessionUser.getId()))  
            return true;
         else 
        	// 重定向到登录页
            response.sendRedirect(contextPath + "/login.do");
            return false;
         
    

/**
 * 用户登录导航
 *
 * @return
 */
@RequestMapping("login.do")
public String login() 
    SessionUser sessionUser = this.getSessionUser();
    if (sessionUser == null) 
        //用户未登录,导航到系统登陆页
        return "login";
     else 
        //用户已登录,导航到系统首页
        return "redirect:/indexController/index.do";
    

以上是关于单体应用如何做用户登录验证及统一拦截(基于session+cookie的登录逻辑怎么做)的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot 统一功能处理

Spring Boot 统一功能处理(用户登录权限效验-拦截器异常处理数据格式返回)

[springboot 开发单体web shop] 5. 用户登录及首页展示

angular中如何设置全局的ajax请求?

简单的实现登录拦截及统一异常处理(自定义异常)

SpringMVC拦截器在用户登录权限中的应用