后台用的是基于Token 的身份验证——JWT(json web token)
1.maven 配置 在pom.xml 中加入如下代码
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>2.2.0</version>
</dependency>
2.新建JWT.java文件(此处我是放到com.demo.filter包下)
package com.demo.filter;
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<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";
private static final String EXP = "exp";
private static final String PAYLOAD = "payload";
//加密,传入一个对象和有效期
public static <T> String sign(T object, long maxAge) {
try {
final JWTSigner signer = new JWTSigner(SECRET);
final Map<String, Object> claims = new HashMap<String, Object>();
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> T unsign(String jwt, Class<T> classT) {
final JWTVerifier verifier = new JWTVerifier(SECRET);
try {
final Map<String,Object> 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;
}
}
}
3.登录时,生成token并传递给前台(ResponseData 类在页末贴出;此处不一定要像下面这种写法,关键是要看生成token那里)
//处理登录
@RequestMapping(value="/login.do", produces = "application/json; charset=utf-8")
public @ResponseBody
ResponseData login(String userName, String password, HttpServletRequest request, HttpServletResponse response) throws Exception{
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
ResponseData responseData = ResponseData.ok();
try{
//先到数据库验证(这一步根据自己的代码逻辑来实现)
User user = service.findUserByNameAndPassword(userName.trim(),CommUtil.generateMD5Str(password));
if(null != user) {
//给用户jwt加密生成token 这里是关键,生成了token 后,怎么给前台返回,那可以用你自己的方法;
String token = JWT.sign(user, 60L* 1000L* 30L);
//封装成对象返回给客户端
responseData.putDataValue("token", token);
responseData.putDataValue("user", user);
}
else{
responseData = ResponseData.customerError();
}
}catch (Exception e){
e.printStackTrace();
}
return responseData;
}
4.写一个拦截;拦截访问的请求
package com.demo.util;
import com.alibaba.fastjson.JSONObject;
import com.demo.bean.User;
import com.demo.filter.JWT;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
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");
//此处是前台将token和loginId 放到了headers里面,后来来获取并处理
String token = request.getHeader("X-Token");
String loginId = request.getHeader("X-LoginId");
ResponseData responseData = ResponseData.ok();
//token不存在
if(null != token) {
User user = JWT.unsign(token, User.class);
//解密token后的loginId与用户传来的loginId不一致,一般都是token过期
if(null != loginId && null != user) {
if(Integer.parseInt(loginId) == user.getId()) {
return true;
}
else{
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
}
else
{
responseData = ResponseData.forbidden();
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) {
responseData = ResponseData.forbidden();
response.setContentType("application/json; charset=utf-8");
String json = JSONObject.toJSONString(responseData);
out.print(json);
out.flush();
out.close();
}
}
5.spring-mvc.xml中配置拦截
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/**" />
<!-- /register.do 和 /login.do 不需要拦截(这里根据项目具体需求来配置)-->
<mvc:exclude-mapping path="/register.do" />
<mvc:exclude-mapping path="/login.do" />
<bean class="com.demo.util.TokenInterceptor"></bean>
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>
6.后台拦截已经做完,接下来是前端vue+axios 配置了
在main.js中对axios进行配置
import Vue from 'vue'
import axios from 'axios'
Vue.prototype.axios = axios
// 请求时的拦截
axios.interceptors.request.use(function (config) {
// 发送请求之前做一些处理
//在登录的时候,后台会将token和loginId传递过来,拿到值以后,用localStorage.setItem("jwt",JSON.stringify(data));存起来
let storageData = localStorage.getItem("jwt");
if(storageData){
storageData = JSON.parse(storageData);
let token = storageData.token,
loginId = storageData.loginId;
config.headers['X-Token'] = token;
config.headers['X-LoginId'] = loginId;
}
return config;
}, function (error) {
// 当请求异常时做一些处理
return Promise.reject(error);
});
// 响应时拦截
axios.interceptors.response.use(function (response) {
// 返回响应时做一些处理
console.log("返回的数据",response);
return response;
}, function (error) {
// 当响应异常时做一些处理
return Promise.reject(error);
});
7.附上ResponseData 代码
package com.demo.util;
import java.util.HashMap;
import java.util.Map;
public class ResponseData {
private final String message;
private final int code;
private final Map<String, Object> data = new HashMap<String, Object>();
public String getMessage() {
return message;
}
public int getCode() {
return code;
}
public Map<String, Object> getData() {
return data;
}
public ResponseData putDataValue(String key, Object value) {
data.put(key, value);
return this;
}
private ResponseData(int code, String message) {
this.code = code;
this.message = message;
}
public static ResponseData ok() {
return new ResponseData(200, "Ok");
}
public static ResponseData notFound() {
return new ResponseData(404, "Not Found");
}
public static ResponseData badRequest() {
return new ResponseData(400, "Bad Request");
}
public static ResponseData forbidden() {
return new ResponseData(403, "Forbidden");
}
public static ResponseData unauthorized() {
return new ResponseData(401, "unauthorized");
}
public static ResponseData serverInternalError() {
return new ResponseData(500, "Server Internal Error");
}
public static ResponseData customerError() {
return new ResponseData(1001, "customer Error");
}
}