JavaWeb阶段学习知识点(二)
登录校验和JWT令牌实现
JWT使用方式
创建一个springboot项目,pom.xml引入jwt依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- 针对jdk17
或者报错内容为:java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter 的
小伙伴加一下下面的依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
在测试类中,定义一个测试方法,测试jwt令牌生成
package com.jwz;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class test {
/**
* 生成jwt
*/
@Test
void testSetJwt() {
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("name","xiaoji");
/**
* builder:用来构建jwt令牌
* signWith: 生成jwt令牌使用的数字算法(jwt.io),官网有,参数一指定算法,参数二就是签名秘钥,这个随便写,但是切记不要少于5个字符,否则报错
* setClaims:设置自定义数据(载荷)
* setExpiration:设置令牌有效期,System.currentTimeMillis()+3600 当前时间+3600秒,也就是3600*1000毫秒后令牌过期,就是设置有效期为一小时
* compact:调用compact可以拿到一个字符串类型的返回值
*/
String jinweizhe = Jwts.builder().signWith(SignatureAlgorithm.HS256, "jinweizhe").setClaims(claims).setExpiration(new Date(System.currentTimeMillis() + 3600*1000)).compact();
System.out.println("生成的jwt为: "+jinweizhe); // 这个打印的就是jwt令牌
// 生成的jwt为: eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoieGlhb2ppIiwiaWQiOjEsImV4cCI6MTcxNjIxODU2OH0.4-yMVfNWyb87TFryq8FJTiH_AAXLsmYGOFVybyjK15g
}
/**
* 解析jwt
*/
@Test
void testGetJwt(){
/**
* setSigningKey:指定签名秘钥
* parseClaimsJws:传入jwt令牌
* getBody:拿到自定义内容
*/
Claims jinweizhe = Jwts.parser().setSigningKey("jinweizhe").parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoieGlhb2ppIiwiaWQiOjEsImV4cCI6MTcxNjIxODU2OH0.4-yMVfNWyb87TFryq8FJTiH_AAXLsmYGOFVybyjK15g").getBody();
System.out.println("解析到的jwt为: "+jinweizhe); // 解析到的jwt为: {name=xiaoji, id=1, exp=1716218568}
}
}
- JWT校验时使用的签名秘钥,必须和生成IWT令牌时使用的秘钥是配套的
- 如果JWT令牌解析校验时报错,则说明JWT令牌被篡改 或 失效了,令牌非法。
过滤器filter的使用操作
- 定义Filter:定义一个类,实现 Filter 接口,并重写其所有方法。
- 配置Filter:filter类上加 @WebFiter 注解,配置拦截资源的路径。引导类上加 @ServletComponentscan 开启Servlet组件支持,
登录校验流程
- 获取请求url。
- 判断请求url中是否包含login,如果包含,说明是登录操作,放行
- 获取请求头中的令牌(token)
- 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
- 解析token,如果解析失败,返回错误结果(未登录)
- 放行。
在SpringBoot项目下,新建一个utils包和DemoFilter类
这里说明一下,下面用到的Result和JwtUtils都是工具包,下面有完整的项目代码,里面是有包含的,这里就不写出来了,可以往下翻找到完整项目代码
DemoFilter类内容如下
package com.jwz.login;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*") // 拦截所有的请求
// @WebFilter(urlPatterns = "/emps/*") // 访问emps下的所有资源的,都会被拦截
// @WebFilter(urlPatterns = "/login") // 拦截具体接口
public class DemoFilter implements Filter {
// 还有init和destroy分别对应初始化方法和销毁方法,都只会调用一次,这两个不用重写,因为查看Filter源码会发现底层已经默认调用了,当然,想重写也可以
// 这里只关注doFilter即可,他会在拦截到请求之后开始调用,会调用多次
@Override // 拦截到请求之后调用,会调用多次,拦截到接口需要放行,否则接口不返回数据
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// System.out.println("拦截到请求了...放行之前的逻辑");
// // 放行接口
// // 参数1:请求对象 参数2:响应对象
// // 放行后可以发现能正常返回数据了
// filterChain.doFilter(servletRequest,servletResponse);
// System.out.println("拦截到请求了...放行之后的逻辑");
// 下面是登录校验的实现思路
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
// 将请求头和响应头都设置utf-8的格式,避免请求和响应结果有中文造成了乱码
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json; charset=UTF-8");
//1.获取请求ur1.
String url = req.getRequestURL().toString();
log.info("请求的url:{}",url);
//2.判断请求url中是否包含login,如果包含,说明是获录操作,放行。
if(url.contains("login")){
log.info("登录操作,直接放行");
filterChain.doFilter(servletRequest,servletResponse);
return; // 停止代码继续向下执行
}
//3.获取请求头中的令牌(token)。
String token = req.getHeader("token");
//4.判断令牌是否存在、如果不存在,返回错误结果(未发录)
if(!StringUtils.hasLength(token)){
// 判断字符串是否有长度
log.info("请求头token为空,返回未登录信息");
Result error = Result.error("未登录"); // 这里的Result是一个工具类,笔记下面的完整项目里面有工具文件代码
// 手动转换 对象 -- json -----> 阿里巴巴fastJSON工具包(https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2/2.0.50)
// 去上面地址复制代码到pom.xml依赖下载一下
String noLogin = JSONObject.toJSONString(error); // 获取到json字符串(对象转成了json字符串)
resp.getWriter().write(noLogin); // 将结果响应给浏览器
return;
}
//5.解析token,如果解析失败,返回误结果(未录)
// 这里的JwtUtils也是个工具类,跟上面的Result一样,下翻完整代码里面有工具类代码提供
try {
JwtUtils.parseJWT(token);
} catch (Exception e) {
// e.printStackTrace();
log.info("令牌解析失败,返回未登录的错误信息");
Result error = Result.error("未登录");
String noLogin = JSONObject.toJSONString(error); // 获取到json字符串(对象转成了json字符串)
resp.getWriter().write(noLogin); // 将结果响应给浏览器
return;
}
//6.放行。
log.info("令牌合法,直接放行");
filterChain.doFilter(servletRequest, servletResponse);
}
}
启动类新增一个注解
package com.jwz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan // 开启了对servlet组件的支持
@SpringBootApplication
public class LoginVeifillyApplication {
public static void main(String[] args) {
SpringApplication.run(LoginVeifillyApplication.class, args);
}
}
测试用的controller
package com.jwz.login;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class loginController {
@PostMapping("/login")
public Result login(@RequestBody loginEntity login){
// 登陆成功,生成jwt并下发jwt返回给前端
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put
原文地址:https://blog.csdn.net/weixin_68658847/article/details/139871341
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!