大家好,欢迎来到IT知识分享网。
springboot整合JWT
一、封装工具类
public class JWTUtils {
private static String SECRET = "token!Q@W#E$R"; / * 生产token */ public static String getToken(Map<String, String> map) {
JWTCreator.Builder builder = JWT.create(); //payload map.forEach((k, v) -> {
builder.withClaim(k, v); }); Calendar instance = Calendar.getInstance(); instance.add(Calendar.DATE, 7); //默认7天过期 builder.withExpiresAt(instance.getTime());//指定令牌的过期时间 String token = builder.sign(Algorithm.HMAC256(SECRET));//签名 return token; } / * 验证token */ public static DecodedJWT verify(String token) {
//如果有任何验证异常,此处都会抛出异常 DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token); return decodedJWT; } }
二、搭建环境
1、数据库
就是一个表,三个字段
创建一个springboot项目,省略了。。。。
2、导入依赖包
mysql,lombok,mybatis-plus,jwt
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
3、数据库配置文件
#数据库连接配置 spring.datasource.username=root spring.datasource.password= #mysql5~8 驱动不同driver-class-name 8需要增加时区的配置serverTimezone=UTC #useSSL=false 安全连接 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus_study_one?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
4、封装JWT工具类
public class JWTUtils {
private static String SECRET = "token!Q@W#E$R"; / * 生产token */ public static String getToken(Map<String, String> map) {
JWTCreator.Builder builder = JWT.create(); //payload map.forEach((k, v) -> {
builder.withClaim(k, v); }); Calendar instance = Calendar.getInstance(); instance.add(Calendar.DATE, 7); //默认7天过期 builder.withExpiresAt(instance.getTime());//指定令牌的过期时间 String token = builder.sign(Algorithm.HMAC256(SECRET));//签名 return token; } / * 验证token */ public static DecodedJWT verify(String token) {
//如果有任何验证异常,此处都会抛出异常 DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token); return decodedJWT; } }
5、实体类
@Data @AllArgsConstructor @NoArgsConstructor public class Admin {
@TableId(type = IdType.AUTO) private Integer id; private String name; private String password; }
6、service
public interface AdminService extends IService<Admin> {
/ * 登录接口 * * @param admin 表单中的user * @return 数据库中查询到的User */ Admin login(Admin admin); }
7、servicelmpl
@Service public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
@Autowired private AdminMapper adminMapper; @Override public Admin login(Admin admin) {
QueryWrapper<Admin> wrapper = new QueryWrapper<>(); wrapper.eq("name",admin.getName()); wrapper.eq("password",admin.getPassword()); System.out.println(admin.getName()); System.out.println(admin.getPassword()); //若出现多个结果使用list或map Admin adminDB = adminMapper.selectOne(wrapper); //查询一个数据,若出现多个结果使用list或map if (adminDB != null) {
return adminDB; } throw new RuntimeException("认证失败"); } }
8、mapper
@Repository public interface AdminMapper extends BaseMapper<Admin> {
}
完成的目录结构如下:
三、生成token
写一下controller
@RestController public class AdminController {
@Autowired private AdminService adminService; @GetMapping("/user/login") public Map<String, Object> login(Admin admin) {
Map<String, Object> map = new HashMap<>(); try {
Admin adminDB = adminService.login(admin); Map<String, String> payload = new HashMap<>(); payload.put("id", Integer.toString(adminDB.getId())); payload.put("name", adminDB.getName()); String token = JWTUtils.getToken(payload); map.put("state", true); map.put("msg", "登录成功"); map.put("token", token); return map; } catch (Exception e) {
e.printStackTrace(); map.put("state", false); map.put("msg", e.getMessage()); map.put("token", ""); } return map; } }
使用postman,输入正确的账号密码,token创建成功
输入错误的账号密码,则失败
四、验证token
在admincontroller加上一个验证方法
@PostMapping("/user/test") public Map<String, Object> test(String token) {
Map<String,Object> map = new HashMap<>(); System.out.println(token); try {
DecodedJWT verify = JWTUtils.verify(token); //验证令牌 map.put("state",true); map.put("msg","请求成功"); return map; } catch (SignatureVerificationException e) {
e.printStackTrace(); map.put("msg","无效签名"); } catch (TokenExpiredException e) {
e.printStackTrace(); map.put("msg","token过期!"); } catch (AlgorithmMismatchException e) {
e.printStackTrace(); map.put("msg","token算法不一致"); } catch (Exception e) {
e.printStackTrace(); map.put("msg","token无效"); } map.put("state",false); return map; }
生成一个token后验证,成功
把token修改之后,验证,失败
五、拦截器
通过上面的代码可以发现,是不是以后每写一个接口,都要先写一堆的验证代码验证一下啊?就非常的冗余,不合理,所以要解决掉这个问题。使用拦截器。
5.1 定义拦截器
public class JWTInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的令牌 String token = request.getHeader("token"); System.out.println(token); Map<String, Object> map = new HashMap<>(); try {
JWTUtils.verify(token); return true; } catch (SignatureVerificationException e) {
e.printStackTrace(); map.put("msg", "签名不一致"); } catch (TokenExpiredException e) {
e.printStackTrace(); map.put("msg", "令牌过期"); } catch (AlgorithmMismatchException e) {
e.printStackTrace(); map.put("msg", "算法不匹配"); } catch (InvalidClaimException e) {
e.printStackTrace(); map.put("msg", "失效的payload"); } catch (Exception e) {
e.printStackTrace(); map.put("msg", "token无效"); } map.put("state", false); //响应到前台: 将map转为json String json = new ObjectMapper().writeValueAsString(map); response.setContentType("application/json;charset=UTF-8"); response.getWriter().println(json); return false; } }
5.2 注册拦截器
@Configuration public class InterceptorConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor()) .addPathPatterns("/user/test") //这个是拦截的路径 .excludePathPatterns("/user/login") //这个是不拦截的路径 ; } }
5.3 获取JWT中的payload
修改一下admincontroller
@PostMapping("/user/test") public Map<String, Object> test(HttpServletRequest request) {
String token = request.getHeader("token"); DecodedJWT verify = JWTUtils.verify(token); String id = verify.getClaim("id").asString(); String name = verify.getClaim("name").asString(); System.out.println(id); System.out.println(name); // 业务逻辑 Map<String, Object> map = new HashMap<>(); map.put("state", true); map.put("msg", "请求成功"); return map; }
添加修改完之后,整体是这样的
重启一下项目,验证一下效果
生成token之后,在头部加入token,OK没有问题
一键三连有没有捏~~
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/139309.html