环境
jdk1.8+springboot+maven
使用场景
授权登录校验
引入依赖
<!--java web token-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
编写工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
public class JwtUtils {
/**
* 创建token
* @param userId
* @return
*/
public static String createToken(String userId,String nickName){
if(nickName == null){
nickName = "";
}
return JWT.create().withAudience(userId)//签发对象
.withIssuedAt(new Date())
.withClaim("nickName",nickName)//负载值
.withClaim("userId",userId)
.sign(Algorithm.HMAC256(userId+"myAppCheck"));//使用HMAC算法,userId+myAppCheck 作为密钥加密
}
/**
* 校验
* @param token
* @param secret
*/
public static boolean verifyToken(String token,String secret){
DecodedJWT jwt = null;
try{
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+"myAppCheck")).build();
jwt = verifier.verify(token);
return true;
}catch (Exception e){
return false;
}
}
/**
* 获取签发对象
* @param token
* @return
*/
public static String getAudience(String token){
String audience = null;
try{
audience = JWT.decode(token).getAudience().get(0);
}catch (Exception e){
//token解析失败
}
return audience;
}
/**
* 获取负载值
* @param token
* @param name
* @return
*/
public static Claim getClaimByName(String token,String name){
return JWT.decode(token).getClaim(name);
}
}
使用
用户在进行登录时,生成token并返回,之后访问的请求中携带改token
String token = JwtUtils.createToken(userVo.getUserId(),userVo.getNickName());
创建一个注解,用于跳过登录验证(若不想使用注解,也可以在拦截器中配置不拦截的路径)
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;
}
编写拦截器
import com.myapp.tool.annotation.PassToken;
import com.myapp.tool.baseTool.JwtUtils;
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 JwtInterceptorAuth implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");//获取token,这里token我放在header上,所以在header获取
if(!(handler instanceof HandlerMethod)){
return true;
}
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
//判断是否需要登录验证(是否有PassToken注解)
if(method.isAnnotationPresent(PassToken.class)){
PassToken passToken = method.getAnnotation(PassToken.class);
if(passToken.required()){
return true;
}
}else{
System.out.println("拦截认证!");
if(token == null){
System.out.println("需要登录!");
notTokenReturn(response);
return false;
}
String userId = JwtUtils.getAudience(token);
if(!JwtUtils.verifyToken(token,userId)){
notTokenReturn(response);
return false;
}else{
//可以获取负载中的值
String userName = JwtUtils.getClaimByName(token,"userName").asString();
request.setAttribute("userName",userName);
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
private void notTokenReturn(HttpServletResponse response) throws Exception{
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("没登录");//这里返回的数据自己定义
response.getWriter().flush();
}
}
配置一下拦截器拦截所有路径请求
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截器配置
*/
@Configuration
public class JwtInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptorAuth())
.addPathPatterns("/**");
}
@Bean
public JwtInterceptorAuth jwtInterceptorAuth(){
return new JwtInterceptorAuth();
}
/**
* 设置返回格式
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
控制层(拿用户登录做个例子)
/**
* 用户登录
* @param u
* @return
*/
@PassToken
@GetMapping(value = "/login")
public String login(User u){
//判断用户是否存在
UserVo userVo = userService.selectUserByLogin(u.getLoginName(),u.getPassWord());
if(userVo == null){
throw new CustomException(ReturnCode.MC999,"用户名或密码错误");
}
//生成token并返回
String token = JwtUtils.createToken(userVo.getUserId(),userVo.getNickName());
Map reMap = new HashMap();
reMap.put("user",userVo);
reMap.put("token",token);
if(StringUtils.isNotBlank(u.getcId()) ){
userService.updateCid(userVo.getUserId(),u.getcId());
}
return ReturnData.reJson(reMap);
}
水平有限,仅供参考。