一.后端
后端目录:
1.pom依赖需引入jwt
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
2.token工具类,用来生成token以及校验token
public class TokenUtil {
public static void main(String[] args) {
User u = new User("admin","123");
System.out.println(sign(u));
}
private static final long EXPIRE_TIME = 10*60*60*1000;
private static final String PRIVATE_KEY = "abcde"; //密钥
/**
* 签名生成
* @param user
* @return
*/
public static String sign(User user){
String token = null;
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
Map<String,Object> claims = new HashMap<>();
//自定义有效载荷部分
claims.put("account",user.getUserId());
token = Jwts.builder()
//发证人
.setIssuer("auth")
//Jwt头
.setHeader(header)
//有效载荷
.setClaims(claims)
//设定签发时间
.setIssuedAt(new Date())
//设定过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
//使用HS256算法签名,PRIVATE_KEY为签名密钥
.signWith(SignatureAlgorithm.HS256,PRIVATE_KEY)
.compact();
return token;
}
/**
* 验证 token信息 是否正确
* @param token 被解析 JWT
* @return 是否正确
*/
public static boolean verify(String token){
//获取签名密钥
//String key = userEntity.getUserPassword();
//获取DefaultJwtParser
try{
Jwts.parser()
//设置 密钥
.setSigningKey(PRIVATE_KEY)
//设置需要解析的 token
.parseClaimsJws(token).getBody();
return true;
}catch (Exception e){
return false;
}
}
}
3.TokenInterceptor 拦截器
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
// 重写 前置拦截方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
System.out.println("OPTIONS请求,放行");
return true;
}
// 1、从请求头中获取token
String token = request.getHeader("token");
System.out.println(token);
// 2、判断 token 是否存在
if (token == null || "".equals(token)) {
System.out.println("未登录");
return false;
}
// 3、解析token
if(!TokenUtil.verify(token)){
return false;
}
return true;
}
}
4.WebMvcConfig 注册拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
// 注入 token 拦截器
@Autowired
private TokenInterceptor interceptor;
/**
* 重写添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加自定义拦截器,并拦截对应 url"
registry.addInterceptor(interceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
}
5.User实体类
public class User {
private String userId;
private String password;
public User(String id,String word){
this.userId = id;
this.password = word;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
6.controller接口
@CrossOrigin
@RestController
public class UserController{
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public String login(@RequestBody Map<String,String> para) throws JsonProcessingException {
String username=para.get("username");
String password=para.get("password");
String token= TokenUtil.sign(new User(username,password));
HashMap<String,Object> hs=new HashMap<>();
hs.put("token",token);
ObjectMapper objectMapper=new ObjectMapper();
return objectMapper.writeValueAsString(hs);
}
@RequestMapping(value = "/demo",method = RequestMethod.POST)
public String hello(){
System.out.println("sdhfkhsdf");
return "Nihao ";
}
}
二.前端
前端目录:one.vue页面是多余的 不用管
1.登录页面
<template>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="auto" class="demo-ruleForm" >
<el-form-item label-width="300px" >
</el-form-item>
<el-form-item label="账号:" label-width="50px" prop="pass">
<el-input clearable name="name" type="username" v-model.trim="ruleForm.pass" autocomplete="off" placeholder="请输入账号" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label="密码:" label-width="50px" prop="checkPass">
<el-input clearable name="word" type="password" v-model.trim="ruleForm.checkPass" autocomplete="off" placeholder="请输入密码" style="width: 250px"></el-input>
</el-form-item>
<el-form-item label-width="95px">
<el-button type="primary" @click="handleSubmit">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
export default {
data () {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入账号'))
}
}
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
}
}
return {
ruleForm: {
pass: '',
checkPass: ''
},
userToken: '',
userid: '',
userword: '',
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
]
}
}
},
methods: {
handleSubmit () {
let params = {
'username': this.ruleForm.pass,
'password': this.ruleForm.checkPass
}
this.$axios.post('http://localhost:8080/login', params).then(res => {
// 请求成功
console.log(res.data)
this.userToken = res.data.token
// 将用户token保存
alert(this.userToken)
localStorage.setItem('token', this.userToken)
this.$router.push('/main')
}).catch(() => {
// 请求失败,
this.$Message.error('登录失败!请检查登录信息是否正确!')
})
}
}
}
</script>
.login{
position: absolute;/绝对定位/
width: 300px;
height: 200px;
text-align: center;/(让div中的内容居中)/
top: 50%;
left: 50%;
margin-top: -200px;
margin-left: -150px;
}
</style>
2.登录成功后的main页面(为了测试,就只写了一个按钮,登录成功后,跳转到这个页面,再点击按钮返回一条后端信息)
<template>
<el-button type="primary" @click="mount">登录</el-button>
</div>
</template>
export default {
methods: {
mount () {
alert(localStorage.getItem('token'))
this.$axios.post('http://localhost:8080/demo').then(res => {
// 请求成功
alert(res.data)
}).catch(() => {
// 请求失败,
alert(222)
})
}
}
}
</script>
3.main.js中加入全局配置请求头代码
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import axios from 'axios'
import 'element-ui/lib/theme-chalk/index.css'
import Vuex from 'vuex'
Vue.use(Vuex)
Vue.use(ElementUI)
Vue.prototype.$axios = axios
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
axios.interceptors.request.use(function (config) {
// 为请求头添加Authorization字段为服务端返回的token
config.headers.token = localStorage.getItem('token')
// return config是固定用法 必须有返回值
return config
})
三.测试
前端页面路由:(one这个是多余的不用管,到时候直接输入8081/login页面就行)
打开url:http://localhost:8081/#/login
随便输入账号和密码就行,为了测试,后端没有去从数据库拿数据,登录后跳转到main页面
点击登录按钮:
成功!
本文摘自 :https://www.cnblogs.com/