目录
1.application.yml文件配置
2.JwtUtil文件配置
3.JwtTokenAdminInterceptor拦截器
4.WebMvcConfiguration配置类
5.Controller层
6.测试农户户登录和添加农户
6.1.测试登录:
6.2.将token配置到全局参数里
6.3.测试添加农户操作
练习黑马的苍穹外卖时,因为黑马用的是springboot2,我打算使用springboot3写一个;于是下面就是springboot3整合jjwt:
项目环境:
SpringBoot:3.1.2
JDK:17
jjwt:0.12.3
io.jsonwebtoken jjwt${jjwt.version} 引入这一个就行了
ysy: jwt: # 设置jwt签名加密时使用的秘钥 HMAC-SHA算法32字节 admin-secret-key: ysyysyysyysyysyysyysyysyysyysyys # 设置jwt过期时间 admin-ttl: 7200000 # 设置前端传递过来的令牌名称 admin-token-name: token
import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SecureDigestAlgorithm; import lombok.extern.slf4j.Slf4j; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.Map; /** * @ClassName JwtUtil工具类 * @project agriBlissMart_common * @Description * @Version 1.0 */ @Slf4j public class JwtUtil { /** * 生成jwt * 使用Hs256算法,私钥使用固定密钥 * @param secretKey jwt密钥 * @param ttlMillis jwt过期时间,单位毫秒 * @param claims 设置的信息 * @return */ public static String createJWT(String secretKey, long ttlMillis, Mapclaims){ //指定加密算法 SecureDigestAlgorithm algorithm = Jwts.SIG.HS256; //生成JWT的时间 long expMillis = System.currentTimeMillis()+ttlMillis; Date exp = new Date(expMillis); //密钥实例 SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes()); String compact = Jwts.builder() .signWith(key, algorithm) //设置签名使用的签名算法和签名使用的秘钥 //如果有私有声明,一点要先设置这个自己创建的私有的声明,这个是给builder的claims赋值,一旦卸载标准的声明赋值之后,就是覆盖了那些标准的声明的 .expiration(exp) .claims(claims) //设置自定义负载信息 .compact();//设置过期时间 return compact; } /** * 解析jwt * @param token * @param secretKey * @return */ public static Jws parseJWT(String token, String secretKey){ //密钥实例 SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes()); Jws claimsJws = Jwts.parser() .verifyWith(key) //设置签名的密钥 .build() .parseSignedClaims(token); //设置要解析的jwt return claimsJws; } }
import cn.ysy.constant.JwtClaimsConstant; import cn.ysy.context.BaseContext; import cn.ysy.properties.JwtProperties; import cn.ysy.utils.JwtUtil; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @Component @Slf4j public class JwtTokenAdminInterceptor implements HandlerInterceptor { @Autowired private JwtProperties jwtProperties; /** * 拦截器 校验jwt * @param request * @param response * @param handler * @return * @throws Exception */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ //判断当前拦截到的是Controller的方法还是其他资源 if(!(handler instanceof HandlerMethod)){ //当前拦截到的不是动态方法,直接放行 return true; } //从请求头中获取令牌 String token = request.getHeader(jwtProperties.getAdminTokenName()); //校验令牌 try{ log.info("jwt校验:{}",token); JwsclaimsJws = JwtUtil.parseJWT(token, jwtProperties.getAdminSecretKey()); Long farId = Long.valueOf(claimsJws.getPayload().get(JwtClaimsConstant.FAR_ID).toString()); log.info("当前农户id:{}",farId); BaseContext.setCurrentId(farId); //设置当前登录的用户id //放行 return true; }catch (Exception e){ //不通过,响应401状态码 response.setStatus(HttpStatus.SC_UNAUTHORIZED); return false; } } }
这里面也定义了knife4j;具体的springboot3整合knife4j可以去我主页看看,也是有的
import cn.ysy.interceptor.JwtTokenAdminInterceptor; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * 配置类,注册web层相关组件 * @ClassName WebMvcConfiguration * @Description WebMvcConfiguration * @Version 1.0 */ @Slf4j @Configuration public class WebMvcConfiguration extends WebMvcConfigurationSupport { @Autowired private JwtTokenAdminInterceptor jwtTokenAdminInterceptor; /** * 注册拦截器 * @param registry */ protected void addInterceptors(InterceptorRegistry registry) { log.info("开始注册自定义拦截器。。。"); registry.addInterceptor(jwtTokenAdminInterceptor) .addPathPatterns("/admin/**") .excludePathPatterns("/admin/farmer/login"); } /** * 创建OpenAPI对象 * @return OpenAPI */ @Bean public OpenAPI springShopOpenAPI() { return new OpenAPI() .info(new Info() .title("农智云后台管理系统接口文档") // 接口文档标题 .description("这是基于Knife4j OpenApi3的农智云后台管理系统的接口文档") // 接口文档简介 .version("1.0") // 接口文档版本 .contact(new Contact() .name("乆乄") //开发者 .email("1234567896@qq.com") ) ); // 开发者联系方式 } /** * 添加静态资源映射 * @param registry */ protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
import cn.ysy.constant.JwtClaimsConstant; import cn.ysy.dto.FarmerDTO; import cn.ysy.dto.FarmerLoginDTO; import cn.ysy.entity.Farmer; import cn.ysy.properties.JwtProperties; import cn.ysy.result.Result; import cn.ysy.service.FarmerService; import cn.ysy.utils.JwtUtil; import cn.ysy.vo.FarmerLoginVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @RestController @Slf4j @Tag(name = "农户管理") @RequestMapping("/admin/farmer") public class FarmerController { @Autowired private FarmerService farmerService; @Autowired private JwtProperties jwtProperties; @PostMapping("/login") @Operation(description = "农户登录") public Resultlogin(@RequestBody FarmerLoginDTO farmerLoginDTO){ log.info("登录请求参数:{}",farmerLoginDTO); Farmer farmer = farmerService.login(farmerLoginDTO); //登录成功后,生成jwt令牌 Map claims = new HashMap<>(); claims.put(JwtClaimsConstant.FAR_ID,farmer.getId()); String token = JwtUtil.createJWT( jwtProperties.getAdminSecretKey(), jwtProperties.getAdminTtl(), claims); FarmerLoginVO farmerLoginVO = FarmerLoginVO.builder() .name(farmer.getName()) .token(token) .id(farmer.getId()) .build(); return Result.success(farmerLoginVO); } /** * 农户退出 * @return */ @PostMapping("/logout") @Operation(description = "农户退出") public Result logout(){ return Result.success(); } @PostMapping @Operation(description = "新增农户") public Result save(@RequestBody FarmerDTO farmerDTO){ log.info("新增请求参数:{}",farmerDTO); farmerService.save(farmerDTO); return Result.success(); } }
启动项目。浏览器输入:http://localhost:8080/doc.html
不勾选时:
不勾选时后台是拿不到token的,所以不要忘记勾选
勾选时:
响应成功,刷新数据库查看信息;