vue springboot实现token登录以及访问验证

后端代码:
pom依赖:

		<!--fastjson依赖,用户一会儿前端传值,转换json数据-->
 		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>
        <!--jwt 依赖-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

TokenUtil:

package com.example.demo.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.demo.entity.User;

import java.util.Date;

public class TokenUtil {

    private static final long EXPIRE_TIME= 15*60*1000;
    private static final String TOKEN_SECRET="tokenqkj";  //密钥盐


    /**
     * 签名生成
     * @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("username", user.getUsername())
                    .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("issuer: " + jwt.getIssuer());
            System.out.println("username: " + jwt.getClaim("username").asString());
            System.out.println("过期时间:      " + jwt.getExpiresAt());
            return true;
        } catch (Exception e){
            return false;
        }
    }
}

TokenInterceptor:token拦截器

package com.example.demo.jwt;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

@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");
        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");
        PrintWriter out = null;
        try{
            JSONObject json = new JSONObject();
            json.put("success","false");
            json.put("msg","认证失败,未通过拦截器");
            json.put("code","50000");
            response.getWriter().append(json.toJSONString());
            System.out.println("认证失败,未通过拦截器");
            //        response.getWriter().write("50000");
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }

        return false;

    }
}

IntercepterConfig:入口拦截

package com.example.demo.jwt;

import org.springframework.context.annotation.Configuration;
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 java.util.ArrayList;
import java.util.List;

/**
 * 拦截器配置
 */
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {

    private TokenInterceptor tokenInterceptor;

    //构造方法
    public IntercepterConfig(TokenInterceptor tokenInterceptor){
        this.tokenInterceptor = tokenInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        List<String> excludePath = new ArrayList<>();
        excludePath.add("/user_register"); //注册
        excludePath.add("/login"); //登录
        excludePath.add("/logout"); //登出
        excludePath.add("/static/**");  //静态资源
        excludePath.add("/swagger-ui.html/**");  //静态资源
        excludePath.add("/assets/**");  //静态资源

        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);

    }

    /**
     * 跨域支持
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
                .maxAge(3600 * 24);
    }


}

现在是登录接口,当然,记得配置跨域:
CorsConfig

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        /*是否允许请求带有验证信息*/
        corsConfiguration.setAllowCredentials(true);
        /*允许访问的客户端域名*/
        corsConfiguration.addAllowedOrigin("*");
        /*允许服务端访问的客户端请求头*/
        corsConfiguration.addAllowedHeader("*");
        /*允许访问的方法名,GET POST等*/
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

登录接口:(我这里用的是mybatisplus)

 @PostMapping("/login")
    public ResultMap toLogin(HttpServletResponse response,@RequestBody JSONObject obj){
        System.out.println(obj);
//        String scope= JSONObject.parseObject(obj).getJSONObject("data").getString("scope");
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        obj.getString("password");
        wrapper
                .eq("username",obj.getString("username"))
                .eq("password",obj.getString("password"));

        String token=null;
        User user = userService.getOne(wrapper);
        if(user!=null){
             token = TokenUtil.sign(user);
        }
        // 将token放在响应头
//        response.setHeader(JwtTokenUtil.AUTH_HEADER_KEY, JwtTokenUtil.TOKEN_PREFIX + token);
        if(token != null){

            return resultMap.success().code(200).message(token);
        }
        return  resultMap.success().code(400).message("登录失败,请重试");
    }

现在是vue:(首先安装vuex,我主要是写后端的,感觉这个是个全局变量)
src目录下创建store文件夹,store下 index.js:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const store = new Vuex.Store({
    state: {
        token: localStorage.getItem('token') ? localStorage.getItem('token') : ''
      },
      mutations: {
        setToken (state,token) {
          state.token =token;
          localStorage.setItem("token",token.token);     //存储token
        },
        delToken (state) {
          state.token = '';
          localStorage.removeItem("token");    //删除token
        }
    }    
});

export default store;

然后登录业务(我这里加了element ui 所以看着有点乱,表单验证可以不看,记得在上面引入vuex下的方法,因为main.js没有引入)

<script>
import { mapMutations } from 'vuex';
export default {
  data(){
    return{
        
        loginForm: {
               username:'',
               password:''
        }, 
        //这里是表单验证
        loginFormRules:{
            username:[
                { required: true, message: '请输入用户名称', trigger: 'blur' },
                { min: 2, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }    
            ],
            password:[
                { required: true, message: '请输入用户名称', trigger: 'blur' },
                { min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ]
        }
    }
  },
  
  methods:{
      
    
    //这里是重置按钮,根据¥$refs.xxx获取到东西
    loginFromReset(){
        this.$refs.loginFormRef.resetFields();
    },
    //这里是登录了,先与验证
    // ...mapMutations(['changeLogin']),
    ...mapMutations(['setToken']),
    login(){
        let _this =this;   
        this.$refs.loginFormRef.validate(async valid=>{
               if(!valid){
                   return this.$message.error('请正确填入相应数据');
               }else{
                  
                 const resu = await this.$http.post('login',this.loginForm);
                 console.log(resu.data)
                 if(resu.data.code==200){
                   this.$message.success('登录成功')
                   //把token存进localStorage里面
                //    window.localStorage.setItem("token",resu.data.token)
                console.log(resu.data.message)
                   this.setToken({token: resu.data.message });
                //    this.$store.commit.changeLogin({ token: resu.data.token });
                   this.$router.push({name: 'me'})
                 }else{
                     return this.$message.error('登录失败');
                 }
               }
        });
    }
  }
}
</script>

然后添加路由守卫:

//挂载路由导航守卫
router.beforeEach((to,from,next)=>{
  //to 将要访问的路径
  //from 代表从哪个路径而来
  //next() 代表放行 next('xxx') 强制放行的xxx的路径
  if(to.path==='/'||to.path==='/login'){
    next();
  }else{
    const tokenStr=window.localStorage.getItem('token')
    if(!tokenStr){
     return next('/login')
    }
    next()
  }
})

最后main.js中添加请求拦截器:(这里的config.headers.token中的token是后台定义的要从请求头中那的那个名:{String token = request.getHeader(“token”);}中的token)

// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
  config => {
    if (localStorage.getItem('token')) {
      config.headers.token = localStorage.getItem('token');
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  });  

现在运行:可以看到localStorage中没有token在这里插入图片描述
现在登录

在这里插入图片描述
这里登录成功以后存储了token,然后看看后台
在这里插入图片描述
后台也通过验证,现在试试把token清除然后刷新页面
在这里插入图片描述
刷新
在这里插入图片描述
重定向到登录页,大功告成!

Logo

前往低代码交流专区

更多推荐