当前位置: 代码网 > it编程>编程语言>Java > SpringBoot+vue实现token认证登录过程

SpringBoot+vue实现token认证登录过程

2026年01月07日 Java 我要评论
在spring boot和vue.js中实现token认证登录是一种常见的前后端分离的认证机制。以下是实现这一机制的基本步骤:后端(spring boot)1. 创建用户实体和数据库表首先,你需要定义

在spring boot和vue.js中实现token认证登录是一种常见的前后端分离的认证机制。

以下是实现这一机制的基本步骤:

后端(spring boot)

1. 创建用户实体和数据库表

首先,你需要定义一个用户实体,比如user,并为其创建相应的数据库表。

@tablefield(exist = false)
private string token; // 表示我们数据库没有这个字段,但是在前端我们需要返回这个字段

2. 用户注册和登录接口

在spring boot应用中创建用于注册和登录的rest api。

@override
public user login(userpassworddto userpassworddto) {
    user one = getuserinfo(userpassworddto);
    if (one != null) {
        beanutil.copyproperties(one, userpassworddto, true);
        // 设置token
        string token = tokenutils.gentoken(one.getid().tostring(), one.getpassword());
        one.settoken(token);
        return one;
    }else{
        return null;
    }
}

private user getuserinfo(userpassworddto userpassworddto){
    querywrapper<user> querywrapper = new querywrapper<>();
    querywrapper.eq("username", userpassworddto.getusername());
    querywrapper.eq("password", secureutil.md5(userpassworddto.getpassword()));
    list<user> one =  usermapper.selectlist(querywrapper);
    if (one.size()==0){
        return null;
    }
    return one.get(0);
}

3. jwt token生成

用户登录成功后,生成一个jwt(json web token),并将其发送回客户端。

首先在pom.xml文件中导入jwt包:

<!-- jwt -->
<dependency>
    <groupid>com.auth0</groupid>
    <artifactid>java-jwt</artifactid>
    <version>3.10.3</version>
</dependency>

在config包中新建tokenutils类:

package com.lyk.xuelang.config;

import cn.hutool.core.date.dateutil;
import cn.hutool.core.util.strutil;
import com.auth0.jwt.jwt;
import com.auth0.jwt.algorithms.algorithm;
import com.lyk.xuelang.entity.user;
import com.lyk.xuelang.mapper.usermapper;
import org.springframework.stereotype.component;
import org.springframework.web.context.request.requestcontextholder;
import org.springframework.web.context.request.servletrequestattributes;

import javax.annotation.postconstruct;
import javax.annotation.resource;
import javax.servlet.http.httpservletrequest;
import java.util.date;

@component
public class tokenutils {
    private static usermapper staticusermapper;

    @resource
    private usermapper usermapper;

    @postconstruct
    public void setuserservice() {
        staticusermapper = usermapper;
    }

    /**
     * 生成token
     *
     * @return
     */
    public static string gentoken(string userid, string sign) {
        return jwt.create().withaudience(userid) // 将 user id 保存到 token 里面,作为载荷
                .withexpiresat(dateutil.offsethour(new date(), 2)) // 2小时后token过期
                .sign(algorithm.hmac256(sign)); // 以 password 作为 token 的密钥
    }

    /**
     * 获取当前登录的用户信息
     *
     * @return user对象
     */
    public static user getcurrentuser() {
        try {
            httpservletrequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes()).getrequest();
            string token = request.getheader("token");
            if (strutil.isnotblank(token)) {
                string userid = jwt.decode(token).getaudience().get(0);
                return staticusermapper.selectbyid(integer.valueof(userid));
            }
        } catch (exception e) {
            return null;
        }
        return null;
    }
}

4. jwt token验证

在config包下新建interceptor包,然后新建jwtinterceptor类:

package com.lyk.xuelang.config.interceptor;

import cn.hutool.core.util.strutil;
import com.auth0.jwt.jwt;
import com.auth0.jwt.jwtverifier;
import com.auth0.jwt.algorithms.algorithm;
import com.auth0.jwt.exceptions.jwtdecodeexception;
import com.auth0.jwt.exceptions.jwtverificationexception;
import com.lyk.xuelang.common.constants;
import com.lyk.xuelang.entity.user;
import com.lyk.xuelang.exception.serviceexception;
import com.lyk.xuelang.service.iuserservice;
import org.springframework.stereotype.component;
import org.springframework.web.method.handlermethod;
import org.springframework.web.servlet.handlerinterceptor;

import javax.annotation.resource;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

@component
public class jwtinterceptor implements handlerinterceptor {
    @resource
    private iuserservice userservice;

    @override
    public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
        string token = request.getheader("token");
        if(!(handler instanceof handlermethod)){
            return true;
        }

        // 执行认证
        if (strutil.isblank(token)) {
            throw new serviceexception(constants.code_401, "无token验证失败");
        }
        // 获取 token 中的 userid
        string userid;
        try {
            userid = jwt.decode(token).getaudience().get(0);
        } catch (jwtdecodeexception j) {
            string errmsg = "token验证失败,请重新登录";
            throw new serviceexception(constants.code_401, errmsg);
        }
        // 根据token中的userid查询数据库
        user user = userservice.getbyid(userid);
        if (user == null) {
            throw new serviceexception(constants.code_401, "用户不存在,请重新登录");
        }
        // 用户密码加签验证 token
        jwtverifier jwtverifier = jwt.require(algorithm.hmac256(user.getpassword())).build();
        try {
            jwtverifier.verify(token); // 验证token
        } catch (jwtverificationexception e) {
            throw new serviceexception(constants.code_401, "token验证失败,请重新登录");
        }
        return true;
    }
}

添加自定义拦截器

在config包下新建interceptorconfig类:

package com.lyk.xuelang.config;

import com.lyk.xuelang.config.interceptor.jwtinterceptor;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.servlet.config.annotation.interceptorregistry;
import org.springframework.web.servlet.config.annotation.webmvcconfigurer;

@configuration
public class interceptorconfig implements webmvcconfigurer {

        @override
        // 加自定义拦截器jwtinterceptor,设置拦截规则
        public void addinterceptors(interceptorregistry registry) {
            registry.addinterceptor(jwtinterceptorl())
                    .addpathpatterns("/**") //拦截所有请求,通过判断token是否合法来决定是否登录
                    .excludepathpatterns("/login","/role/page","/**/export","/**/import");//排除这些接口,也就是说,这些接口可以放行
        }
       @bean
       public jwtinterceptor jwtinterceptorl(){
            return new jwtinterceptor();
        }
}

前端(vue.js)

1. 用户界面

创建登录表单,允许用户输入用户名和密码。

<div class="login-container">
  <el-card class="login-card">
    <h2 class="login-title">仓库管理系统</h2>
    <el-form :model="loginform" :rules="rules" ref="loginform" label-width="20">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="loginform.username" placeholder="请输入用户名"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" v-model="loginform.password" placeholder="请输入密码"></el-input>
      </el-form-item>
      <el-form-item style="margin: 10px 0;text-align: right;" label="温馨提示:忘记密码?联系管理员!">
        <el-button type="primary" autocomplete="off" @click="submitform">登录</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</div>

2. 发送登录请求

用户提交表单后,前端发送登录请求到后端的登录接口。

login.js代码如下:

import request from '@/utils/request'

// 用户登录
export function login (user) {
  return request({
    url: '/login',
    method: 'post',
    data: user
  })
}

home.vue页面代码如下:

<script>
import { login } from '@/api/login'

export default {
  data () {
    return {
      loginform: {
        username: '',
        password: ''
      },
      rules: {
        username: [
          { required: true, message: '请输入用户名!', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码!', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    submitform () {
      this.$refs.loginform.validate(async (valid) => {
        if (valid) {
          // 在这里添加你的登录逻辑
          const res = await login(this.loginform)
          if (res.code === 200) {
            this.$message.success('登录成功')
            localstorage.setitem('user', json.stringify(res.data)) // 存储用户信息到浏览器
            localstorage.setitem('token', json.stringify(res.data.token))
            this.$router.push('/main')
          } else {
            this.$message.error(res.msg)
          }
        } else {
          this.$message.error('账号密码错误,请重新输入!')
          return false
        }
      })
    }
  }
}
</script>

3. 接收并存储token

登录成功后,前端接收jwt token,并将其存储在本地存储(localstorage)或vuex状态管理中。

// 在这里添加你的登录逻辑
const res = await login(this.loginform)
if (res.code === 200) {
  this.$message.success('登录成功')
  localstorage.setitem('user', json.stringify(res.data)) // 存储用户信息到浏览器
  localstorage.setitem('token', json.stringify(res.data.token))
  this.$router.push('/main')
}

4. 发送请求时携带token

在发送需要认证的请求时,前端需要在请求头中携带jwt token。

// 添加请求拦截器,一下内容是axios的拦截器,可以不用写
request.interceptors.request.use(config => {
  config.headers['content-type'] = 'application/json;charset=utf-8'
  const user = localstorage.getitem('user') ? json.parse(localstorage.getitem('user')) : null
  if (user) {
    config.headers.token = user.token
  }

  return config
}, error => {
  return promise.reject(error)
})

5. 路由守卫

使用vue router的路由守卫来保护需要认证的路由。

{ path: '/dashboard', 
    component: dashboard,
    meta: 
       {requiresauth: true} 
} // 标记需要验证的路由
router.beforeeach((to, from, next) => {
  const auth = require('@/router/auth').default // 引入认证守卫
  auth.redirectifnotauthenticated(to, from, next)
})

auth.js代码如下:

export default {
  isauthenticated () {
    // 这里应该根据你的应用逻辑来检查用户是否登录
    // 例如,检查本地存储(localstorage)中是否有token
    return localstorage.getitem('token') !== null
  },

  redirectifnotauthenticated (to, from, next) {
    if (!this.isauthenticated()) {
      to.path !== '/login' && to.matched.some(record => record.meta.requiresauth) ? next({ path: '/login' }) : next()
    } else {
      next()
    }
  }
}

注意事项

  • 安全性:确保使用https来传输jwt token。
  • token存储:考虑使用httponly的cookie来存储token,以避免xss攻击。
  • token过期:jwt token应该有过期时间,并且后端需要处理token的刷新。

这只是一个简单的示例,实际应用中可能需要更复杂的逻辑,比如密码加密、token刷新机制、用户角色和权限管理等。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com