springBoot+Vue 的token登录验证的使用

springBoot+Vue 的token登录验证的使用

前端Vue

登录页请求代码:

 // 登入
function login(){
    if(user.userCode === "" || user.userPassword === ""){
        flag.value = true
        msg.value = "账号或者密码不能为空"
    }else{
        // md加密 (我这里前后端都对密码进行了md5加密,你们测试这里可以不需要,如果需要就要下载md的包)
        user.userPassword = md5(user.userPassword)
        let userString = JSON.stringify(user)
        // 登入请求
        proxy.$axios.post(`${proxy.PATH}/login/${userString}`).then(
            response=>{
                const data = response.data;

                if(data.is_login){//登录成功
                    localStorage.setItem("token",data.token)	//保存token
                    localStorage.setItem("userCode",data.userCode)
                    router.push({//登录成功后进行跳转
                        name:"manage"
                    })
                }else{
                    msg.value = data.msg 
                    flag.value = true
                }
            },
            error=>{
                console.log('请求失败了',error.message)
            }
        )
    }
}

每次向后端发送请求的时候都带上这个token,这个可以设置到mian.js

// 每次请求前 有token就带上
axios.interceptors.request.use( config => {
    const token = localStorage.getItem("token");
    if(token !== null && token !== ""){
        config.headers.token = token;
    }
    return config
})

为了防止没有token或者token不正确的也不能进入需要登录的页面,还设置了前置路由守卫

const PATH = "http://localhost:8888/blog"
//全局前置路由守卫,权限检测,初始化时也会被调用
router.beforeEach((to,from,next)=>{
    const path = to.path
    //判断请求路径中是否带有这个地址
    if(path.indexOf("/blog/manage/") != -1 ){
        const token = localStorage.getItem("token");
        if(token !== null && token !== ""){//是否带有token
            axios.get(`${PATH}/token/${token}`).then(//去后端判断这个token是否正确
                response=>{
                    if(response.data){//正确就放行
                        next();
                    }else{//错误就跳到登录页
                        next("/blog/login")
                    }
                },
                error=>{
                    console.log('请求失败了',error.message)
                })
        }else{
            next("/blog/login")
        }
    }else{
        next()
    }
})

后端springBoot

需要导入上传token的设密依赖jwt

<!-- token jwt加密 解密 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

编写生成token和判断token是否正确的的工具类

package com.mhy.blog.utils;

import com.mhy.blog.pojo.User;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtils {
//    签名过期时间 10个小时
    private static final long EXPIRE_TIME = 10*60*60*1000;
//    签名秘钥 可以自己设定
    private static final String PRIVATE_KEY = "shuisanya";
//    生成token
    public static String sign(User user){
        String token = "";
        Map<String,Object> header = new HashMap<>();

        header.put("typ","JWT");
        header.put("alg","HS256");

        Map<String ,Object> claims = new HashMap<>();

//        自定义有效荷载部分
        claims.put("account",user.getUserCode());

        token = Jwts.builder()
//                发证人
                .setIssuer("auth")
//                jwt头
                .setHeader(header)
//                有效负荷
                .setClaims(claims)
//                设定签订时间
                .setIssuedAt(new Date())
//                设定过期时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
//                使用SignatureAlgorithm.HS256算法,加密,秘钥是:PRIVATE_KEY
                .signWith(SignatureAlgorithm.HS256,PRIVATE_KEY)
                .compact();

        return token;
    }

//    生成token是否正确
    public static boolean verify(String token){

        try {
            Jwts.parser()
                .setSigningKey(PRIVATE_KEY)
                .parseClaimsJws(token).getBody();
            return true;
        }catch (Exception e){
            return false;
        }
    }
}

配置拦截器,需要拦截哪些请求需要token

options请求的官方定义:OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。
其实就是:在发生正式的请求之前,先进行一次预检请求。看服务端返回一些信息,浏览器拿到之后,看后台是否允许进行访问。

package com.mhy.blog.interceptor;

import com.mhy.blog.utils.TokenUtils;
import org.springframework.http.HttpMethod;
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 {
//这里一定不要忘了设置OPTIONS这个跨域请求,第一个请求一般不带token,然后会发起第二次请求带token
        if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){
//            System.out.println("跨域的第一次 OPTIONS 放行");
            return true;
        }

//        System.out.println("拦截了 manage");
//        从请求头中获取token
        String token = request.getHeader("token");
//        System.out.println(token);

//        判断token是否正确
        if(token == null || token.equals("token")){
//            System.out.println("未登入");
            return false;
        }
//        解析token
        if(!TokenUtils.verify(token)){
//            System.out.println("解析失败");
            return false;
        }

        return true;
    }

}

不要忘记把拦截器加入到配置中,说明你需要拦截的内容

    private TokenInterceptor interceptor;
    @Autowired//装配拦截器
    public void setInterceptor(TokenInterceptor interceptor) {
        this.interceptor = interceptor;
    }
//解决跨域请求
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //放行哪些原始域
                .allowedOriginPatterns(ConstUtils.PATH_ORIGIN)
                //是否发送Cookie
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .maxAge(30*1000)
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
//配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(interceptor)
                .addPathPatterns("/manage/**");
    }

登录请求的Controller

    /**
     * 登入功能
     * @param user 前端的用户登入信息
     * @return 返回登录情况
     */
    @PostMapping("/login/{user}")
    public Map<String,Object> login(@PathVariable String user){
        Map<String,Object> userMap = JSONObject.parseObject(user, (Type)Map.class);
        Map<String,Object> result = new HashMap<>();

//        	  登入验证
        if(loginService.login(userMap)){
//            登入成功
            User userToken = new User();
//            设置token
            userToken.setUserCode((String) userMap.get("userCode"));
            userToken.setUserCode((String) userMap.get("userPassword"));
            String token = TokenUtils.sign(userToken);
            result.put("token",token);
            result.put("userCode",userMap.get("userCode"));
//            设置返回信息
            result.put("msg",ConstUtils.LOGIN_SUCCESS);
            result.put("is_login",true);
        }else {
//            登入失败
            result.put("msg",ConstUtils.LOGIN_FAILURE);
            result.put("is_login",false);
        }

        return result;
    }

这样就大工完成了

测试看看吧:

总结下

其实这就是在加密与解密,利用到了一些http请求的知识,你也可以自己设计加密与解密!!!

没有多么的神奇

posted @ 2022-08-09 21:25  水三丫  阅读(1257)  评论(0编辑  收藏  举报