实现Token的方式有很多,本篇介绍的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什么好处呢?
本篇分3部分进行讲解。
JSON Web Token 简称JWT。
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
JWT生成的token是这样的
eyJpc3MiOiJKb2huI.eyJpc3MiOiJ.Kb2huIFd1IEp
生成的token,是3段,用.连接。下面有解释。
用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
例如:
{
"typ": "JWT",
"alg": "HS256"
}
其实就是自定义的数据,一般存储用户Id,过期时间等信息。也就是JWT的核心所在,因为这些数据就是使后端知道此token是哪个用户已经登录的凭证。而且这些数据是存在token里面的,由前端携带,所以后端几乎不需要保存任何数据。
例如:
{
"uid": "xxxxidid", //用户id
"exp": "12121212" //过期时间
}
签名其实就是:
JWT的原理参考文章
com.auth0
java-jwt
3.4.0
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
public class JWT {
private static final String SECRET = "XX#$%()(#*!()!KL<>?N<:{LWPW";
private static final String EXP = "exp";
private static final String PAYLOAD = "payload";
//加密,传入一个对象和有效期
public static String sign(T object, long maxAge) {
try {
final JWTSigner signer = new JWTSigner(SECRET);
final Map claims = new HashMap();
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(object);
claims.put(PAYLOAD, jsonString);
claims.put(EXP, System.currentTimeMillis() + maxAge);
return signer.sign(claims);
} catch(Exception e) {
return null;
}
}
//解密,传入一个加密后的token字符串和解密后的类型
public static T unsign(String jwt, Class classT) {
final JWTVerifier verifier = new JWTVerifier(SECRET);
try {
final Map claims= verifier.verify(jwt);
if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
long exp = (Long)claims.get(EXP);
long currentTimeMillis = System.currentTimeMillis();
if (exp > currentTimeMillis) {
String json = (String)claims.get(PAYLOAD);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, classT);
}
}
return null;
} catch (Exception e) {
return null;
}
}
}
import org.springframework.beans.factory.annotation.Autowired;
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;
import com.hc.interceptor.TokenInterceptor;
@Configuration
public class WebConfigurer extends WebMvcConfigurationSupport {
@Autowired
private TokenInterceptor tokenInterceptor;
// 这个方法是用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**") 表示拦截所有的请求,
// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**","/Typhoon/**","/Nephogram/**","/Ocean/**","/Siteinfo/**","/Siteinfo/**", "/User/**");
super.addInterceptors(registry);
}
}
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.hc.config.JWT;
import com.hc.pojo.User;
import com.hc.util.ResponseData;
@Component
public class TokenInterceptor implements HandlerInterceptor{
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception arg3)
throws Exception {
}
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView model) throws Exception {
}
//拦截每个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token =request.getHeader("Authorization");
ResponseData responseData = ResponseData.ok();
//token不存在
if(null != token) {
User user = JWT.unsign(token, User.class);
if(null != user) {
return true;
}else{
responseData = ResponseData.tokenOverdue();
responseMessage(response, response.getWriter(), responseData);
return false;
}
}
else
{
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
}
//请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
response.setContentType("application/json; charset=utf-8");
String json = JSONObject.toJSONString(responseData);
out.print(json);
out.flush();
out.close();
}
}
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hc.config.JWT;
import com.hc.pojo.User;
import com.hc.service.UserService;
import com.hc.util.ResponseData;
@Controller
@RequestMapping(value = "/User", produces = MediaType.APPLICATION_JSON_VALUE)
@CrossOrigin(origins="*")
public class UserController {
@Autowired
private UserService userService;
private static final Integer rolename = 1;//管理员权限
/**
* 权限判断
* */
public boolean token(String token) {
User user = JWT.unsign(token, User.class);
if(user.getRole()==rolename) {
return true;
}else {
return false;
}
}
/**
* 用户添加
* */
@RequestMapping("addUser")
@ResponseBody
public Object addUser(User user,@RequestHeader("Authorization") String token) {
if(token(token)) {
Integer num = userService.addUser(user);
if(num > 0) {
return user.getId();
}else {
return ResponseData.serverInternalError();
}
}else {
return ResponseData.unauthorized();
}
}