登录认证实现两种技术方案

288 阅读4分钟

登录功能 登录校验

登录功能的本质是什么?
就是 查询

根据用户名和密码查询员工信息

登录校验反而更加复杂 这里 我有两种技术方案:

其一 客户端Cookie+服务端Session

在一次会话中可以包含多次请求和响应。 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。 会话跟踪方案: 客户端Cookie+服务端Session

核心工作原理

  1. 认证流程

    • 用户登录时,服务端创建Session并存储用户数据(如用户ID、角色)
    • 服务端通过Set-Cookie响应头将SessionID返回客户端,浏览器自动保存Cookie
    • 后续请求时,浏览器自动在请求头Cookie中携带SessionID,服务端通过SessionID验证用户身份
  2. 数据存储位置

    组件存储位置数据内容
    Cookie客户端浏览器仅包含SessionID(加密字符串)2
    Session服务端内存/数据库用户完整数据(如权限、登录时间)

下面就该写代码了,由于用的mvc结构 先从controller层写起,请忽略注解,注解功能我会新开一篇文章来写

-   Controller:接收请求参数(用户名、密码),调用Service方法,响应结果。

@RestController
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp,
                        HttpSession session) {
        LoginInfo LoginInfo = empService.login(emp);
        System.out.println("LoginInfo = " + LoginInfo);
        if (LoginInfo == null) {
            return Result.error("用户名或密码错误");
            session.setAttribute("loginUser", LoginInfo);
            return Result.success(LoginInfo);
            }
    }
    调用 `EmpService` 的 `login` 方法,传入 `Emp` 对象进行登录验证。
    `login` 方法返回一个 `LoginInfo` 对象,包含登录成功后的相关信息。
    同时打印 `LoginInfo` 对象,方便调试。


-   Service:根据用户名和密码查询员工信息,判定并组装数据返回。
    LoginInfo login(Emp emp);
    //写在接口里
@Override
//自然是接口实现类啦
public LoginInfo login(Emp emp) {
    Emp emp1 = empMapper.selectByUsernameAndPassword(
            emp.getUsername(),
            emp.getPassword()
    );
    System.out.println("emp1 = " + emp1);
    System.out.println(" = -----  =");
    if (emp1 != null) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setId(emp1.getId());
        loginInfo.setUsername(emp1.getUsername());
        loginInfo.setName(emp1.getName());
        return loginInfo;
    }
    return null;
    
}
偷个懒,mapper不精细写了
-   Mapper:执行SQL查询,
如`select * from emp where username = ? and password = ?`。

客户端Cookie + 服务端Session‌:

  • 优点:代码实现简单快捷。
  • 缺点:移动端APP无法使用Cookie,
  • 用户可以自己禁用Cookie,
  • Cookie不能跨域,
  • 服务器集群环境下无法直接使用Session。

听说这个方案已经是好多年前的了,只有技术比较老的公司用

新策略

令牌技术(JWT) ‌:

  • 优点:支持PC端、移动端,解决集群环境下的认证问题,减轻服务器端存储压力。
  • 缺点:需要自己实现。
JWT令牌技术

1. JWT令牌介绍

  • 全称:JSON Web Token(jwt.io/)。

  • 组成:

    • Header(头):记录令牌类型、签名算法等。
    • Payload(有效载荷):携带一些自定义信息、默认信息等。
    • Signature(签名):防止Token被篡改,确保安全性。

2. JWT令牌生成/解析

  • 引入jjwt依赖。
  • 使用Jwts.builder()生成令牌,Jwts.parser()解析令牌。
  • 写在工具类里,用直接调用就行

3. JWT令牌注意事项

  • JWT令牌由header、payload、signature三部分组成。
  • 生成及校验JWT令牌时,使用的签名秘钥必须配套。
  • 解析令牌时,如果令牌被篡改或过期失效,会报错。
四、登录校验实现

1. 过滤器(Filter)

  • 概念‌:JavaWeb三大组件之一,可以拦截对资源的请求,实现特殊功能,如登录校验、统一编码处理等。

  • 开发步骤‌:

    • 定义:实现Filter接口(init、doFilter、destroy)。
    • 配置:使用@WebFilter注解配置拦截路径,使用@ServletComponentScan开启Servlet组件支持。
    • @WebFilter(urlPatterns = "/*")//拦截所有请求
    • @ServletComponentScan放到启动类里

-**令牌校验Filter流程**‌:

    -   获取请求URL,判断是否为登录请求,如果是则放行。
    -   获取请求头中的令牌,判断令牌是否存在,如果不存在则响应401。
    -   解析令牌,如果解析失败则响应401。
    -   放行合法请求。

-**Filter执行流程**‌:放行前 -> 放行 -> 资源访问 -> 放行后。

-**Filter拦截路径**‌:可以配置为拦截所有资源(`/*`)或特定目录下的资源(如`/emps/*`)。

-**过滤器链**‌:项目中多个过滤器形成的链,按照过滤器类名的自然排序执行。

2. 拦截器(Interceptor)

  • 概念‌:Spring框架中提供的,用于动态拦截控制器方法的执行。

  • 使用步骤‌:

    • 定义:实现HandlerInterceptor接口(preHandle、postHandle、afterCompletion)。
    • 配置:定义一个配置类实现WebMvcConfigurer接口,注册拦截器。
  • 令牌校验Interceptor流程‌:与Filter类似,但只拦截Spring环境中的资源。

  • 拦截路径‌:可以配置为拦截所有资源(/**)或特定路径。注意/*/**;的区别,前者只能拦截一级路径,后者可以拦截任意级路径。

  • 执行流程‌:preHandle(控制器方法执行前)-> 控制器方法执行 -> postHandle(控制器方法执行后)-> afterCompletion(视图渲染完毕后)。

3. Filter与Interceptor的区别

  • 接口规范不同‌:过滤器实现Filter接口,拦截器实现HandlerInterceptor接口。
  • 拦截范围不同‌:过滤器拦截所有资源,拦截器只拦截Spring环境中的资源。