- springboot 代码

首先在entity 新建实体,新建代码
java
package com.example.demo.demos.web.demo.entity;
import lombok.Data;
@Data
public class User {
private String username;
private String password;
private String token;
}
- controller 中写

java
//定义两个初始常量登录名 这里不使用数据库认证
private final String USERNAME = "admin";
private final String PASSWORD = "admin";
@GetMapping("/login")
public User login( User loginForm){
if(USERNAME.equals(loginForm.getUsername()) && PASSWORD.equals(loginForm.getPassword())){
//添加token
loginForm.setToken(JwtUtiles.createToken());
return loginForm;
}
return null;
}
添加相关依赖
xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--- 注意以下是 java1.8以上需要添加--->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
utils 中新建 文件JwtUtiles

java
package com.example.demo.demos.web.demo.utils;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.UUID;
public class JwtUtiles {
private static long time = 1000* 60 *60 *24;//token有效时间
private static String signature = "admin";
public static String createToken(){
JwtBuilder jwtBuilder = Jwts.builder();
String jwtToken = jwtBuilder
.setHeaderParam("typ","JWT")
.setHeaderParam("alg","HS256")
.claim("username","admin")
.claim("role","admin")
.setSubject("admin-test")
.setExpiration(new Date(System.currentTimeMillis()+time))
.setId(UUID.randomUUID().toString())
.signWith(SignatureAlgorithm.HS256,signature)
.compact();
return jwtToken;
}
}
前端vue 写法:
request.js 配置

html
import axios from 'axios'
const request = axios.create({
baseURL: 'http://localhost:8080',
timeout: 50000
})
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
let user=localStorage.getItem("user")?JSON.parse(localStorage.getItem("user")):{}//获取登录时存放的user对象信息
config.headers['token'] = user.token; // 设置请求头
return config
}, error => {
return Promise.reject(error)
});
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default request
login.vue 界面
html
<template>
<div class="login_container">
<div class="login_box">
<div style="margin:20px 0; text-align:center; font-size:24px" ><b>登录</b></div>
<!-- 用户名-->
<el-form ref="LoginFormRef" :model="loginForm" :rules="LoginFormRules" >
<el-form-item prop="username">
<el-input size="medium" style="margin:10px 0px;width: 300px;margin-left:25px" v-model="loginForm.username" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<!-- 密码-->
<el-form-item prop="password">
<el-input size="medium" style="margin:10px 0px;width: 300px;margin-left:25px" show-password v-model="loginForm.password" prefix-icon="el-icon-lock" type="password"></el-input>
</el-form-item>
<div style="margin:10px 0; text-align:center">
<el-button type="primary" size="small" @click="login" >登录</el-button>
<!-- <el-button type="warning" size="small" @click="resetLoginForm">重置</el-button> -->
</div>
</el-form>
</div>
</div>
</template>
<script>
export default {
name:"Login",
data() {
return {
loginForm: {
username:'',
password:''
},
LoginFormRules:{
username:[
{ required: true, message: '请输入用户名', trigger: 'blur' },
],
password:[
{ required: true, message: '请输入密码', trigger: 'blur' },
]
}
}
},
methods:{
login(){
this.$refs['LoginFormRef'].validate(async (valid) => {
if (valid) {
let _this = this;
this.request.get("http://localhost:8080/user/login",{params:this.loginForm}).then(res=>{
console.log(this.loginForm)
console.log(res)
/* if(res.code=='200'){
localStorage.setItem("user",JSON.stringify(res.data));//存储用户信息到浏览器
this.$router.push("/home");
this.$message.success("登录成功");
}else{
this.$message.error(res.msg);
} */
})
}
})
},
}
}
</script>
<style scoped>
.login_container{
background-color: #2b4b6b;
height: 100%;
}
.login_box{
width: 350px;
height: 300px;
background-color: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%)
}
</style>

登录后可观察到token已经返回

添加路由守卫

js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Manage from '../views/Manage.vue'
import Aside from '@/components/Aside.vue'
import User from '@/views/user.vue'
import Login from '../views/Login.vue'
import axios from 'axios'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Manage',
redirect: '/login',
component: Manage,
children:[
{
path: 'user',
name: 'User',
component: User
},
{
path: 'home',
name: 'Home',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Home.vue')
}
]
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/error',
name: 'Error',
component: Login
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
//全局路由守卫
router.beforeEach((to,from,next)=>{
if(to.path.startsWith('/login')){
window.localStorage.removeItem('access-admin')
next()
}else{
let admin = JSON.parse(window.localStorage.getItem('access-admin'))
console.log(admin)
if(!admin ){
next({path:'/login'})
location.reload()
}else{//检查token合法性
let token = admin.token
console.log(token)
axios({
url:"http://localhost:8080/user/checkToken",
method:'get',
Headers:{
token:admin.token
},
params:{
token:token
}
}).then((response) =>{
console.log(response.data)
if(!response.data ){ console.log('校验失败')
// next({path:'/login'})
next({path:'/login'})
location.reload()
}
})
next();
}
}
})
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
export default router
设置到期拦截

java
package com.example.demo.demos.web.demo.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.demos.web.demo.common.Constants;
import com.example.demo.demos.web.demo.common.Result;
import com.example.demo.demos.web.demo.entity.User;
import com.example.demo.demos.web.demo.entity.UserDTO;
import com.example.demo.demos.web.demo.entity.UserEntity;
import com.example.demo.demos.web.demo.mapper.UserMapper;
import com.example.demo.demos.web.demo.service.UserService;
import com.example.demo.demos.web.demo.utils.JwtUtiles;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("user")
public class UserController {
// @Autowired
// private UserMapper userMapper;
@Autowired
public UserService userService;
/* @GetMapping("/")
public List<UserEntity> index(){
return userMapper.findAll();
}*/
//使用mybtis-plus实现查询所有数据
@GetMapping("/")
public List<UserEntity> findAll(){
return userService.list();
}
/* @PostMapping("/add")
//这里做了一个单纯的添加的示例,使用的是mapper中的insert方法
public Integer save(@RequestBody UserEntity userEntity){
return userService.save(userEntity);
}*/
/* @DeleteMapping("/{id}")
public Integer deleteById(@PathVariable Integer id){
return userService.deleteById(id);
}*/
//使用mybtis-plus实现删除
@DeleteMapping("/{id}")
public boolean deleteById(@PathVariable Integer id){
return userService.removeById(id);
}
@PostMapping
//使用mybtis-plus,注意这里返回的是boolean型
public Boolean save(@RequestBody UserEntity user) {
return userService.saveUser(user);
}
//使用mybtis-plus实现批量删除
@PostMapping("/del/batch/")
public boolean deleteBatch(@RequestBody List<Integer> ids){
return userService.removeByIds(ids);
}
//分页查询
//接口路径user/page?pageNum=1&pageSize=10
//RequestParam接受前台传过来的第几页,每页显示数
/* @GetMapping("/page")
public Map<String,Object> findPage(@RequestParam Integer pageNum,@RequestParam Integer pageSize){
pageNum=(pageNum-1)*pageSize;
List<UserEntity> data=userService.selectPage(pageNum,pageSize);
Integer total=userMapper.selectTotal();
Map<String,Object> res=new HashMap<>();
res.put("data",data);
res.put("total",total);
return res;
}*/
//使用mybtis-plus实现根据ID查找记录
@GetMapping("/{id}")
public UserEntity findOne(@PathVariable Integer id){
return userService.getById(id);
}
//使用mybtis-plus实现模糊查询并分页
@GetMapping("/page")
public IPage<UserEntity> findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue = "") String username,
@RequestParam(defaultValue = "") String nickname,
@RequestParam(defaultValue = "") String address){
IPage<UserEntity> page=new Page<>(pageNum,pageSize);
QueryWrapper<UserEntity> queryWrapper=new QueryWrapper<>();
queryWrapper.like("username",username);
queryWrapper.like("nickname",nickname);
queryWrapper.like("address",address);
return userService.page(page,queryWrapper);
}
/* @PostMapping("/login")
public Result login(@RequestBody UserDTO userDTO){
String username=userDTO.getUsername();//先对userDTO进行是否为空的校验
String password=userDTO.getPassword();
//调用hutool工具中的StrUtil函数实现用户名和密码是否为空的判断
if(StrUtil.isBlank(username) || StrUtil.isBlank(password)){
return Result.error(Constants.CODE_400,"参数错误");
}
UserDTO dto=userService.login(userDTO);
return Result.success(dto);
}*/
//定义两个初始常量登录名 这里不使用数据库认证
private final String USERNAME = "admin";
private final String PASSWORD = "admin";
@GetMapping("/login")
public User login( User loginForm){
if(USERNAME.equals(loginForm.getUsername()) && PASSWORD.equals(loginForm.getPassword())){
//添加token
loginForm.setToken(JwtUtiles.createToken());
return loginForm;
}
return null;
}
@GetMapping("/checkToken")
public Boolean checkToken(HttpServletRequest request,@RequestParam String token){
String token1 = token;
return JwtUtiles.checkToken(token1);
}
}
写解析方法

java
package com.example.demo.demos.web.demo.utils;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.UUID;
public class JwtUtiles {
private static long time = 1000* 6;//token有效时间
private static String signature = "admin";
public static String createToken(){
JwtBuilder jwtBuilder = Jwts.builder();
String jwtToken = jwtBuilder
.setHeaderParam("typ","JWT")
.setHeaderParam("alg","HS256")
.claim("username","admin")
.claim("role","admin")
.setSubject("admin-test")
.setExpiration(new Date(System.currentTimeMillis()+time))
.setId(UUID.randomUUID().toString())
.signWith(SignatureAlgorithm.HS256,signature)
.compact();
return jwtToken;
}
public static boolean checkToken(String token){
if(token == null){
return false;
}
try {
Jwts.parser().setSigningKey(signature).parseClaimsJws(token);
} catch (Exception e) {
return false;
}
return true;
}
}
login 页面
html
<template>
<div class="login_container">
<div class="login_box">
<div style="margin:20px 0; text-align:center; font-size:24px" ><b>登录</b></div>
<!-- 用户名-->
<el-form ref="LoginFormRef" :model="loginForm" :rules="LoginFormRules" >
<el-form-item prop="username">
<el-input size="medium" style="margin:10px 0px;width: 300px;margin-left:25px" v-model="loginForm.username" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<!-- 密码-->
<el-form-item prop="password">
<el-input size="medium" style="margin:10px 0px;width: 300px;margin-left:25px" show-password v-model="loginForm.password" prefix-icon="el-icon-lock" type="password"></el-input>
</el-form-item>
<div style="margin:10px 0; text-align:center">
<el-button type="primary" size="small" @click="login" >登录</el-button>
<!-- <el-button type="warning" size="small" @click="resetLoginForm">重置</el-button> -->
</div>
</el-form>
</div>
</div>
</template>
<script>
export default {
name:"Login",
data() {
return {
loginForm: {
username:'',
password:''
},
LoginFormRules:{
username:[
{ required: true, message: '请输入用户名', trigger: 'blur' },
],
password:[
{ required: true, message: '请输入密码', trigger: 'blur' },
]
}
}
},
methods:{
login(){
this.$refs['LoginFormRef'].validate(async (valid) => {
if (valid) {
let _this = this;
this.request.get("http://localhost:8080/user/login",{params:this.loginForm}).then(res=>{
// console.log(res)
if(res != null){
localStorage.setItem('access-admin',JSON.stringify(res))
//跳转登录页
// this.$router.replace({path:'/home'})
this.$router.push("/home");
}
// console.log(res)
/* if(res.code=='200'){
localStorage.setItem("user",JSON.stringify(res.data));//存储用户信息到浏览器
this.$router.push("/home");
this.$message.success("登录成功");
}else{
this.$message.error(res.msg);
} */
})
}
})
},
}
}
</script>
<style scoped>
.login_container{
background-color: #2b4b6b;
height: 100%;
}
.login_box{
width: 350px;
height: 300px;
background-color: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%)
}
</style>
