登录功能 登录校验
登录功能的本质是什么?
就是 查询
根据用户名和密码查询员工信息
登录校验反而更加复杂 这里 我有两种技术方案:
其一 客户端Cookie+服务端Session
在一次会话中可以包含多次请求和响应。 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。 会话跟踪方案: 客户端Cookie+服务端Session
核心工作原理
-
认证流程
- 用户登录时,服务端创建Session并存储用户数据(如用户ID、角色)
- 服务端通过
Set-Cookie响应头将SessionID返回客户端,浏览器自动保存Cookie - 后续请求时,浏览器自动在请求头
Cookie中携带SessionID,服务端通过SessionID验证用户身份
-
数据存储位置
组件 存储位置 数据内容 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环境中的资源。