JavaWeb 课堂笔记 —— 21 登录认证
本文介绍了Tlias智能学习辅助系统的登录功能实现与登录校验机制。
登录功能通过POST请求验证用户名密码,成功后发放JWT令牌;登录校验采用统一拦截方式,通过JWT令牌验证用户状态。同时对比了两种会话跟踪技术:客户端Cookie和服务端Session,分别展示了设置和获取方法。文章还提供了SQL查询语句、接口测试结果和代码实现示例,完整呈现了系统认证模块的开发流程。
01 登录功能
① 需求
登录Tlias
智能学习辅助系统,成功后,系统下发JWT
令牌
sql
语句:查询员工并验证username
和password
,其中username
为unique
唯一性。
select * from emp where username = 'jinyong' and password = '123456';
请求路径:/login
请求方式:POST
请求样例:
{
"username":"jinyong",
“password":"123456"
}
响应样例:
{
"code":1,
"msg":"success",
"data":
"eyJhbGcioiJIUzI1Ni]9.eyJuYw11Ijoi6YeR5bq4IiwiawQiojEsInVzZXJuYW11IjoiamlueW9uZzyIsImV4cCI6MTY2MjIWNzA0OH0.KkUc_CXJZJ8Dd063eImx4H90jfrr6XMJyVzaWCVZCo"
}
② 思路
创建一个新的controller
文件,添加注解@PostMapping
和@RequestBody
(json
格式数据),登录操作的是员工信息,借助EmpService.java
和EmpMapper.java
实现,返回登录成功或失败。
③ 牛马开发
④ Postman
测试
⑤ 前后端联调测试
02 登录校验
① 需求
该页面存在隐患,用户不用输入用户名和密码就可以直接访问到系统界面,安全性低。需在用户访问界面时自动进行是否登录的判断。若登录,则继续访问;若未登录,则跳转到登录页面。
② 思路
浏览器与服务器之间交互基于http
协议,其是无状态协议,即每次请求都是独立的,下一次请求不会携带上一次请求的数据。
解决方案:
Ⅰ 在所有Controller
接口前加入判断是否登录的操作
Ⅱ 登录之后发放JWT
令牌作为登录标记,每次访问界面时,Web
服务器获取登录标记进行统一拦截(过滤器Filter
、拦截器Intercepter
)
03 传统web
会话技术
会话:用户打开浏览器来访问web
服务器的资源,会话建立;某方断开连接,会话结束。一次会话包含多次请求和响应。
会话跟踪:一种维护浏览器状态的方法,通过识别多次请求是否来自同一浏览器,来实现一次会话内部数据共享。
① 客户端(浏览器)会话跟踪技术:Cookie
SessionController.java
测试文件
package com.itheima.controller;import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** HttpSession演示*/
@Slf4j
@RestController
public class SessionController {//设置Cookie(对应 3 → 4 操作)@GetMapping("/c1")public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookiereturn Result.success();}//获取Cookie(对应 1 → 2 操作)@GetMapping("/c2")public Result cookie2(HttpServletRequest request){Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if(cookie.getName().equals("login_username")){System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie}}return Result.success();}
}
设置cookie
获取cookie
优点:http
官方支持
缺点:手机软件无法使用、用户随意禁用Cookie
、无法跨域(协议、IP
地址/域名、端口号)
② 服务端会话跟踪技术:Session
package com.itheima.controller;import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** HttpSession演示*/
@Slf4j
@RestController
public class SessionController {//先手@GetMapping("/s1")public Result session1(HttpSession session){log.info("HttpSession-s1: {}", session.hashCode());session.setAttribute("loginUser", "tom"); //往session中存储数据return Result.success();}//后手@GetMapping("/s2")public Result session2(HttpServletRequest request){HttpSession session = request.getSession();log.info("HttpSession-s2: {}", session.hashCode());Object loginUser = session.getAttribute("loginUser"); //从session中获取数据log.info("loginUser: {}", loginUser);return Result.success(loginUser);}
}
往session
中存储数据:
从session
中获取数据:
Console
控制台:
优点:服务端存储
缺点:服务器集群不支持、Cookie
所有缺点
③ 令牌技术
优点:支持PC
端、移动端、支持服务器集群、减轻服务端存储
缺点:自己实现
04 JWT
令牌
JWT(JSON Web Token)
令牌定义了一种简介的、自包含的格式,用于在通信双方以json
数据格式安全的传递信息。
① 组成
② 应用场景:登录认证
登录成功后,生成令牌,后续每个请求,都要携带WT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理。
③ 生成JWT
令牌
TliasWebManagementApplicationTests.java
/*** 生成JWT令牌*/@Testpublic void testGenJwt(){Map<String, Object> claims = new HashMap<>();claims.put("id",1);claims.put("name","Tom");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256,"itheima") //签名算法.setClaims(claims)//有效期一小时.setExpiration(new Date(System.currentTimeMillis() + 3600*1000)) .compact(); //JWT令牌System.out.println(jwt);}
Console
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTc0OTgxMTMwMH0.GMAJ0yF9jNMzO5jhrQ4QHYzjCi9X-4MpD8OmvG1eSlo
④ 解析JWT
令牌
TliasWebManagementApplicationTests.java
@Testpublic void testParseJwt(){Claims claims = Jwts.parser()//密钥.setSigningKey("itheima")//JWT令牌.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4c"+"CI6MTc0OTgxMTMwMH0.GMAJ0yF9jNMzO5jhrQ4QHYzjCi9X-4MpD8OmvG1eSlo")//第二部分.getBody();System.out.println(claims);}
Console
{name=Tom, id=1, exp=1749811300}
注:ⅠJWT
校验时使用的签名秘钥,必须和生成JWT
令牌时使用的密钥是配套的
Ⅱ 如果JWT
令牌解析校验时报错,则说明JWT
令牌被篡改或失效了,令牌非法
⑤ 返回JWT
令牌
05 牛马开发
引入JWT
令牌操作工具类,登录完成后,调用工具生成JWT
令牌,并返回。
LoginController.java
@Slf4j
@RestController
public class LoginController {//注入EmpService对象@Autowiredprivate EmpService empService;@PostMapping("/login")//username和password由emp实体类接收即可//@RequestBody将json格式数据封装为emp实体类public Result login(@RequestBody Emp emp){log.info("员工登录:{}", emp);Emp e = empService.login(emp);//登录成功,生成并下发令牌if(e != null){Map<String, Object> claims = new HashMap<>();claims.put("id", e.getId());claims.put("name", e.getName());claims.put("username", e.getUsername());JwtUtils.generateJwt(claims); //jwt包含当前登录的员工信息return Result.success();}//登录失败,返回错误信息return Result.error("用户名或密码错误");}
}