springboot中使用token
1. pom.xml文件中添加依赖<!-- 引入操作JWT的相关依赖 --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.11.0</version></dependency&
·
1. pom.xml文件中添加依赖
<!-- 引入操作JWT的相关依赖 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.11.0</version>
</dependency>
除此依赖之外还需要添加springbootweb的起步依赖,以及使用的数据库依赖
2. 定义工具类JwtUtil.java
package com.cowstone.util;
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 java.util.Date;
import java.util.Map;
public class JwtUtil {
/**
* 过期5分钟
* */
private static final long EXPIRE_TIME = 5 * 60 * 1000;
/**
* jwt密钥
* */
private static final String SECRET = "jwt_secret";
/**
* 生成jwt字符串,五分钟后过期 JWT(json web token)
* @param userId
* @param info,Map的value只能存放值的类型为:Map,List,Boolean,Integer,Long,Double,String and Date
* @return
* */
public static String sign(String userId, Map<String, Object> info) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(SECRET);
return JWT.create()
//将userId保存到token里面
.withAudience(userId)
//存放自定义数据
.withClaim("info", info)
//五分钟后token过期
.withExpiresAt(date)
//token的密钥
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据token获取userId
* @param token
* @return
* */
public static String getUserId(String token) {
try {
String userId = JWT.decode(token).getAudience().get(0);
return userId;
}catch (JWTDecodeException e) {
return null;
}
}
/**
* 根据token获取自定义数据info
* @param token
* @return
* */
public static Map<String, Object> getInfo(String token) {
try {
return JWT.decode(token).getClaim("info").asMap();
}catch (JWTDecodeException e) {
return null;
}
}
/**
* 校验token
* @param token
* @return
* */
public static boolean checkSign(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
//.withClaim("username, username)
.build();
verifier.verify(token);
return true;
}catch (JWTVerificationException e) {
throw new RuntimeException("token 无效,请重新获取");
}
}
}
3. 定义Controller类
package com.cowstone.controllers;
import com.cowstone.service.UserService;
import com.cowstone.util.JwtUtil;
import com.cowstone.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@RestController
public class TestController {
@GetMapping("/author/hello")
public String hello() {
return "hello world";
}
@GetMapping("/auth/login")
public Result login(String username, String pass) {
//假设数据库中查询到了该用户,这里测试先所及生成一个UUID,作为用户的id
String userId = UUID.randomUUID().toString();
//准备存放在IWT中的自定义数据
Map<String, Object> info = new HashMap<>();
info.put("username", "tom");
info.put("pass", "admin");
//生成JWT字符串
String token = JwtUtil.sign(userId, info);
return Result.success("token:" + token);
}
}
4. 定义拦截器
package com.cowstone.interceptor;
import com.cowstone.util.JwtUtil;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
//从 http 请求头中取出 token
String token = request.getHeader("token");
System.out.println("此处测试是否拿到了token:" + token);
if (token == null) {
throw new RuntimeException("无 token ,请重新登陆");
}
//验证 token
JwtUtil.checkSign(token);
//验证通过后, 这里测试取出JWT中存放的数据
//获取 token 中的 userId
String userId = JwtUtil.getUserId(token);
System.out.println("id : " + userId);
//获取 token 中的其他数据
Map<String, Object> info = JwtUtil.getInfo(token);
info.forEach((k, v) -> System.out.println(k + ":" + v));
return true;
}
}
5. 定义javaConfig类
package com.cowstone.config;
import com.cowstone.interceptor.JwtInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 添加jwt拦截器,并指定拦截路径
* */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/author/**");
}
/**
* jwt拦截器
* */
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
}
6. 启动项目,访问/author/hello
可以看出,目前请求中没有携带token,所以返回错误的信息
7. 访问/auth/login,获取登陆后的token
8. 把获取到的token值复制到请求头中
9. 再次访问/author/hello
可以看出得到了正确的答案
10. 到后台查看拦截器输出的结果
11. 以上代码中用到了Result类以及ResultCode类,在此处额外补充说明
package com.cowstone.util;
import java.io.Serializable;
public class Result implements Serializable {
private static final long SerialVersionUID = 1L;
private Integer code;
private String msg;
private Object data;
private Result() {}
private Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
private void setResultCode(ResultCode code) {
this.code = code.code();
this.msg = code.message();
}
/**
* 操作失败,自定义code和msg
* */
public static Result failure(Integer code, String msg) {
Result result = new Result(code, msg);
return result;
}
/**
* 操作成功,没有返回的数据
* */
public static Result success() {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
return result;
}
/**
* 操作成功,有返回的数据
* */
public static Result success(Object data) {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
result.setData(data);
return result;
}
/**
* 操作失败,没有返回的数据
* */
public static Result failure(ResultCode resultCode) {
Result result = new Result();
result.setResultCode(resultCode);
return result;
}
/**
* 操作失败,有返回的数据
* */
public static Result failure(ResultCode resultCode, Object data) {
Result result = new Result();
result.setResultCode(resultCode);
result.setData(data);
return result;
}
public static long getSerialVersionUID() {
return SerialVersionUID;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
package com.cowstone.cms.util;
/**
* 统一并自定义返回状态码,如有需求可以另外增加
*/
public enum ResultCode {
/* 默认成功状态码 */
SUCCESS(1, "操作成功"),
/* 默认失败状态码 */
ERROR(2, "操作失败,未知指定错误信息"),
/* 参数错误:10001-19999 */
PARAM_IS_INVALID(10001, "参数无效"),
PARAM_IS_BLANK(10002, "参数为空"),
PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"),
PARAM_NOT_COMPLETE(10004, "参数缺失"),
/* 用户错误:20001-29999*/
USER_NOT_LOGIN(20001, "用户未登录"),
USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
USER_NOT_EXIST(20004, "用户不存在"),
USER_HAS_EXISTED(20005, "用户已存在"),
/* 业务错误:30001-39999 */
SPECIFIED_QUESTIONED_USER_NOT_EXIST(30001, "业务逻辑出现问题"),
/* 系统错误:40001-49999 */
SYSTEM_INNER_ERROR(40001, "系统内部错误,请稍后重试"),
/* 数据错误:50001-599999 */
DATA_NONE(50001, "数据未找到"),
DATA_WRONG(50002, "数据错误"),
DATA_EXISTED(50003, "数据已存在"),
/* 接口错误:60001-69999 */
INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),
INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
/* 权限错误:70001-79999 */
PERMISSION_NO_ACCESS(70001, "无访问权限");
private Integer code;
private String message;
ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer code() {
return this.code;
}
public String message() {
return this.message;
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)