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请求的知识,你也可以自己设计加密与解密!!!
没有多么的神奇
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)