Spring boot+VUE实现token验证
阐述了spring boot+vue前后端分离项目中如何使用token进行验证
·
Spring boot+VUE实现token验证
Vue+Spring Boot实现token认证主要可分为六步:
1.前端登录,post用户名和密码到后端。
2.后端验证用户名和密码,若通过,生成一个token返回给前端。
3.前端拿到token用vuex和localStorage管理,登录成功进入首页。
4.之后前端每一次权限操作如跳转路由,都需要判断是否存在token,若不存在,跳转至登录页。
5.前端之后的每一个对后端的请求都要在请求头上带上token,后端查看请求头是否有token,拿到token检查是否过期,返回对应状态给前端。(通常失败返回401)
6.若token已过期,清除token信息,跳转至登录页。
一、添加依赖
<!--添加jwt 依赖-->
<!-- maven -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.19.1</version>
</dependency>
<!-- gradle -->
implementation group: 'com.auth0', name: 'java-jwt', version: '3.19.1'
二、添加token工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.lin.springMVC.domain.User;
import java.util.Date;
public class TokenUtil {
private static final long EXPIRE_TIME= 10*60*60*1000;
private static final String TOKEN_SECRET="test"; //密钥盐
/**
* 签名生成
* @param user
* @return
*/
public static String sign(User user){
String token = null;
try {
Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME);
token = JWT.create()
.withIssuer("auth0")
.withClaim("userAccount", user.getUserAccount())
.withExpiresAt(expiresAt)
// 使用了HMAC256加密算法。
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (Exception e){
e.printStackTrace();
}
return token;
}
/**
* 签名验证
* @param token
* @return
*/
public static boolean verify(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT jwt = verifier.verify(token);
System.out.println("认证通过:");
System.out.println("userAccount: " + jwt.getClaim("userAccount").asString());
System.out.println("过期时间: " + jwt.getExpiresAt());
return true;
} catch (Exception e){
return false;
}
}
}
三、创建拦截器
import com.alibaba.fastjson.JSONObject;
import com.haiyang.utils.TokenUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
if(request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token"); //前端vue将token添加在请求头中
if(token != null){
boolean result = TokenUtil.verify(token);
if(result){
System.out.println("通过拦截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try{
JSONObject json = new JSONObject();
json.put("msg","token verify fail");
json.put("code","50000");
response.getWriter().append(json.toJSONString());
System.out.println("认证失败,未通过拦截器");
}catch (Exception e){
e.printStackTrace();
response.sendError(500);
return false;
}
return false;
}
}
四、配置跨域
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;
import com.haiyang.Interceptor.TokenInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 开启跨域
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路由
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOriginPatterns("*")
// 是否允许携带cookie参数
.allowCredentials(true)
// 设置允许的方法
.allowedMethods("*")
// 跨域允许时间
.maxAge(3600);
}
private TokenInterceptor tokenInterceptor;
//构造方法
public WebMvcConfig(TokenInterceptor tokenInterceptor){
this.tokenInterceptor = tokenInterceptor;
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer){
configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
configurer.setDefaultTimeout(30000);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
//排除拦截,除了注册登录(此时还没token),其他都拦截
excludePath.add("/admin/register"); //登录
excludePath.add("/admin/login"); //注册
excludePath.add("/img/**"); //静态资源
excludePath.add("/song/**"); //静态资源
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
五、登录接口
@ResponseBody
@GetMapping("/login")
public Object login(User user){
User u = userService.userLogin(user);
JSONObject jsonObject = new JSONObject();
if (u != null){
String token = TokenUtil.sign(u);
jsonObject.put("token",token);
jsonObject.put("user",u);
jsonObject.put("msg","登录成功");
jsonObject.put("code",200);
}else{
jsonObject.put("msg","账号或密码错误");
jsonObject.put("code",500);
}
return jsonObject;
}
六、前端配置
(1)main.js配置
1.添加路由前置守卫beforeEach拦截请求:
//路由全局前置守卫
router.beforeEach((to,from,next) => {
if(to.path === '/register' || to.path === '/login' || to.path === '/'){ //若是进入登录与注册页面 ==> pass
next()
}else{
let userToken = localStorage.getItem('token');
console.log("Token为:"+userToken);
if(userToken == null || userToken == ''){
alert("无权限,请先登录!");
return next('/login');
}else{
next();
}
}
}),
-
在axios中添加请求拦截器:
//请求拦截器 在请求头中加token axios.interceptors.request.use( config => { if(localStorage.getItem('token')){ config.headers.token = localStorage.getItem('token'); } return config; }, error => { return Promise.reject(error); } )
(2)配置Vuex
const store = new Vuex.Store({
state: {
user: localStorage.getItem('user') ? localStorage.getItem('user') : null,
//若localSorage存在token,将值赋给Vuex.state.token
token: localStorage.getItem('token') ? localStorage.getItem('token') : null,
},
mutations: {
setUser(state, user) {
state.user = user
localStorage.setItem('user', JSON.stringify(user))
},
setToken(state, token) {
localStorage.setItem('token', token)
state.token = token
},
logout(state) {
localStorage.removeItem('token')
state.token = null
localStorage.removeItem('user')
state.user = null
}
}
})
(3)登录方法
login(){
var vm = this
vm.axios.get('http://localhost:8080/login',{
params:{
username:this.username,
password:this.password
}
}).then(function (response) {
if(response.data.code == 200){
console.log(response.data.msg)
//将token和user保存到localStorage中
vm.$store.commit('setToken',response.data.token)
vm.$store.commit('setUser',response.data.user)
//跳转到登录成功后的页面
vm.$router.push({path:'/index'})
else{
alert(response.data.msg)
}
}).catch(function (e) {
console.log(e)
})
}
更多推荐
已为社区贡献2条内容
所有评论(0)