引入jar包:
// https://mvnrepository.com/artifact/com.thetransactioncompany/cors-filter
compile group: 'com.thetransactioncompany', name: 'cors-filter', version: '2.2.1'
// https://mvnrepository.com/artifact/com.thetransactioncompany/java-property-utils
compile group: 'com.thetransactioncompany', name: 'java-property-utils', version: '1.9.1'
// https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
compile group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '4.13.1'
处理跨域:
/**
* 服务端跨域处理过滤器,该过滤器需要依赖cors-filter-2.2.1.jar和java-property-utils-1.9.1.jar
* @author running@vip.163.com
*
*/
@WebFilter(urlPatterns={"/*"},asyncSupported=true,
initParams={
@WebInitParam(name="cors.allowOrigin",value="*"),
@WebInitParam(name="cors.supportedMethods",value="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE"),
@WebInitParam(name="cors.supportedHeaders",value="token,Accept, Origin, X-Requested-With, Content-Type, Last-Modified"),//注意,如果token字段放在请求头传到后端,这里需要配置
@WebInitParam(name="cors.exposedHeaders",value="Set-Cookie"),
@WebInitParam(name="cors.supportsCredentials",value="true")
})
public class WebCorsFilter extends CORSFilter implements javax.servlet.Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("跨域资源处理过滤器初始化了");
super.init(config);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("跨域过滤器");
super.doFilter(request, response, chain);
}
public void setConfiguration(CORSConfiguration config) {
super.setConfiguration(config);
}
}
定义枚举:
package com.shop.utils.JwtUtils;
/**
* 枚举,定义token的三种状态
* @author running@vip.163.com
*
*/
public enum TokenState {
/**
* 过期
*/
EXPIRED("EXPIRED"),
/**
* 无效(token不合法)
*/
INVALID("INVALID"),
/**
* 有效的
*/
VALID("VALID");
private String state;
private TokenState(String state) {
this.state = state;
}
/**
* 根据状态字符串获取token状态枚举对象
* @param tokenState
* @return
*/
public static TokenState getTokenState(String tokenState){
TokenState[] states=TokenState.values();
TokenState ts=null;
for (TokenState state : states) {
if(state.toString().equals(tokenState)){
ts=state;
break;
}
}
return ts;
}
public String toString() {
return this.state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
定义jwt工具:
package com.shop.utils.JwtUtils;
/**
* @author 阳十三
* @email wdful165177@gmail.com
* @blog http://www.item1024.com
* @date 2017/9/5
*/
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import net.minidev.json.JSONObject;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
/**
* 秘钥
*/
private static final byte[] SECRET="diiwneuqeu1231231kiowejfi2".getBytes();
/**
* 初始化head部分的数据为
* {
* "alg":"HS256",
* "type":"JWT"
* }
*/
private static final JWSHeader header=new JWSHeader(JWSAlgorithm.HS256, JOSEObjectType.JWT, null, null, null, null, null, null, null, null, null, null, null);
/**
* 生成token,该方法只在用户登录成功后调用
*
* @param payload,可以存储用户id,token生成时间,token过期时间等自定义字段
* @return token字符串,若失败则返回null
*/
public static String createToken(Map<String, Object> payload) {
payload.put("ext",new Date().getTime()+1000*60*60*5);
payload.put("sign",0);
String tokenString=null;
// 创建一个 JWS object
JWSObject jwsObject = new JWSObject(header, new Payload(new JSONObject(payload)));
try {
// 将jwsObject 进行HMAC签名
jwsObject.sign(new MACSigner(SECRET));
tokenString=jwsObject.serialize();
} catch (JOSEException e) {
System.err.println("签名失败:" + e.getMessage());
e.printStackTrace();
}
return tokenString;
}
/**
* 校验token是否合法,返回Map集合,集合中主要包含 state状态码 data鉴权成功后从token中提取的数据
* 该方法在过滤器中调用,每次请求API时都校验
* @param token
* @return Map<String, Object>
*/
public static Map<String, Object> validToken(String token) {
Map<String, Object> resultMap = new HashMap<String, Object>();
try {
JWSObject jwsObject = JWSObject.parse(token);
Payload payload = jwsObject.getPayload();
JWSVerifier verifier = new MACVerifier(SECRET);
if (jwsObject.verify(verifier)) {
JSONObject jsonOBj = payload.toJSONObject();
// token校验成功(此时没有校验是否过期)
resultMap.put("state", TokenState.VALID.toString());
// 若payload包含ext字段,则校验是否过期
if (jsonOBj.containsKey("ext")) {
long extTime = Long.valueOf(jsonOBj.get("ext").toString());
long curTime = new Date().getTime();
// 过期了
if (curTime > extTime) {
resultMap.clear();
resultMap.put("state", TokenState.EXPIRED.toString());
}
}
resultMap.put("data", jsonOBj);
} else {
// 校验失败
resultMap.put("state", TokenState.INVALID.toString());
}
} catch (Exception e) {
//e.printStackTrace();
// token格式不合法导致的异常
resultMap.clear();
resultMap.put("state", TokenState.INVALID.toString());
}
return resultMap;
}
}
控制器操作 登陆成功后生成token
//生成token
Map<String , Object> payload=new HashMap<String, Object>();
payload.put("user_id",userInfo.getUserId());
String token = JwtUtil.createToken(payload);
Map map = new HashMap();
map.put("msg","登陆成功");
map.put("token",token);
```
# 定义拦截器 拦截需要用户权限的路由 检验token
package com.shop.interceptor;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.shop.utils.JwtUtils.JwtUtil;
import com.shop.utils.JwtUtils.TokenState;
import com.shop.utils.ResultWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoginInterceptor implements HandlerInterceptor{
@Autowired
private RedisTemplate<String,String> redisTemplate;
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 {
System.out.println(request.getRequestURL());
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token");
//token不存在
if (null != token && !token.equals(" ")) {
Map<String, Object> resultMap = JwtUtil.validToken(token);
TokenState state = TokenState.getTokenState((String) resultMap.get("state"));
switch (state) {
case VALID:
//取出payload中数据,放入到request作用域中
request.setAttribute("data", resultMap.get("data"));
//放行
return true;
case EXPIRED:
case INVALID:
default:
System.out.println("无效token");
responseMessage(response, response.getWriter(), new ResultWrapper<>().ErrorWithData("登陆已过期 请重新登录"));
return false;
}
} else {
System.out.println("token = null");
responseMessage(response, response.getWriter(), new ResultWrapper<>().ErrorWithData("您还未登陆"));
// response.sendRedirect(“/login_register.py”);
return false;
}
}
//请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, ResultWrapper resultWrapper) {
response.setContentType("application/json; charset=utf-8");
String json = new Gson().toJson(response);
out.print(json);
out.flush();
out.close();
}
}
“`