一.后端
后端目錄:
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頁面
點擊登錄按鈕:
成功!