springboot之JWT实现权限认证
Posted ywjfx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot之JWT实现权限认证相关的知识,希望对你有一定的参考价值。
1、在pom.xml添加依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
2、自定义两个注解PassToken、UserLoginToken
package com.cn.commodity.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD, ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken boolean required() default true;
package com.cn.commodity.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD, ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken boolean required() default true;
3、定义一个获取token的服务TokenService
package com.cn.commodity.service; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.cn.commodity.entity.User; import org.springframework.stereotype.Service; @Service("tokenService") public class TokenService public String getToken(User user) //生成token String token=""; token= JWT.create().withAudience(String.valueOf(user.getId())) .sign(Algorithm.HMAC256(user.getPassword())); return token;
4、定义一个拦截器
package com.cn.commodity.interceptor; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.JWTVerificationException; import com.cn.commodity.annotations.PassToken; import com.cn.commodity.annotations.UserLoginToken; import com.cn.commodity.entity.User; import com.cn.commodity.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; public class AuthenticationInterceptor implements HandlerInterceptor @Autowired UserService userService; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token // 如果不是映射到方法直接通过 if (!(object instanceof HandlerMethod)) return true; HandlerMethod handlerMethod = (HandlerMethod) object; Method method = handlerMethod.getMethod(); //检查是否有passtoken注释,有则跳过认证 if (method.isAnnotationPresent(PassToken.class)) PassToken passToken = method.getAnnotation(PassToken.class); if (passToken.required()) return true; //检查有没有需要用户权限的注解 if (method.isAnnotationPresent(UserLoginToken.class)) UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class); if (userLoginToken.required()) // 执行认证 if (token == null) throw new RuntimeException("无token,请重新登录"); // 获取 token 中的 user id String userId; try userId = JWT.decode(token).getAudience().get(0); catch (JWTDecodeException j) throw new RuntimeException("401"); User user = userService.getUserById(Integer.parseInt(userId)); if (user == null) throw new RuntimeException("用户不存在,请重新登录"); // 验证 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); try jwtVerifier.verify(token); catch (JWTVerificationException e) throw new RuntimeException("401"); return true; return true; @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception
5、在项目中应用该拦截器
package com.cn.commodity.interceptor; 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.WebMvcConfigurer; @Configuration public class InterceptorConfig implements WebMvcConfigurer @Override public void addInterceptors(InterceptorRegistry registry) registry.addInterceptor(authenticationInterceptor()) .addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录 @Bean public AuthenticationInterceptor authenticationInterceptor() return new AuthenticationInterceptor();
6、在controller层应用注解进行验证
package com.cn.commodity.controller;
import com.alibaba.fastjson.JSONObject;
import com.cn.commodity.annotations.PassToken;
import com.cn.commodity.annotations.UserLoginToken;
import com.cn.commodity.dao.UserDao;
import com.cn.commodity.entity.User;
import com.cn.commodity.service.TokenService;
import com.cn.commodity.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("api")
public class UserApi
@Autowired
UserService userService;
@Autowired
TokenService tokenService;
@Resource
private UserDao userDao;
//登录
@PostMapping("/login")
public Object login(@RequestBody User user)
JSONObject jsonObject=new JSONObject();
//User userForBase=userService.getUserById(user.getId());
User userForBase=userDao.selectOne(user);
if(userForBase==null)
jsonObject.put("message","登录失败,用户不存在");
return jsonObject;
else
if (!userForBase.getPassword().equals(user.getPassword()))
jsonObject.put("message","登录失败,密码错误");
return jsonObject;
else
String token = tokenService.getToken(userForBase);
jsonObject.put("token", token);
jsonObject.put("user", userForBase);
return jsonObject;
@UserLoginToken
@GetMapping("/getMessage")
public String getMessage()
return "你已通过验证";
@PassToken
@GetMapping("/skipToken")
public String skipToken()
return "跳过passToken认证";
7、运行测试
a) 登陆获取token
#获取token,在项目中可以将token和user组合存在redis中。
post请求参数: "userName":"yangwj1", "password":"wj1" 请求url:http://localhost:8080/api/login 返回参数: "user": "id": 2, "userName": "yangwj1", "password": "wj1", "age": 1 , "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyIn0.z2EzbIbYLCmw5PM5Yx9arE5QGUH9ET_AC0BEy9SyE8A"
b)跳过token认证
请求url:http://localhost:8080/api/skipToken 返回参数:跳过passToken认证
c)对api进行token验证
请求参数header中: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyIn0.z2EzbIbYLCmw5PM5Yx9arE5QGUH9ET_AC0BEy9SyE8A 请求url:http://localhost:8080/api/getMessage 返回参数:你已通过验证
以上是关于springboot之JWT实现权限认证的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot整合Shiro+JWT实现认证及权限校验
「干货」SpringBoot+SpringSecurity+Jwt权限认证-认证