Linkaibin 2020-05-08
1-1 运行环境:
后端:jdk1.8,springboot,jwt
前端:vue , elementui
1-2 创建前端和后端项目
后端项目结构:

JwtUtil
package com.swq.jwt.util;
import com.alibaba.fastjson.JSONObject;
import com.swq.jwt.dto.CheckResult;
import com.swq.jwt.entry.User;
import io.jsonwebtoken.*;
import org.apache.tomcat.util.codec.binary.Base64;
import com.swq.jwt.constant.Constant;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
public class JwtUtil {
/**
* 由字符串生成key
*
* @return
*/
public static SecretKey generalKey() {
String Strkey = Constant.JWT_SECRET;//自定义的字符串
byte[] decode = Base64.decodeBase64(Strkey.getBytes());//解密
//利用AES加密算法构造密匙
SecretKey key = new SecretKeySpec(decode, 0, decode.length, "AES");
return key;
}
/**
* @param id JWT的唯一标识
* @param subject
* @param ttl 过期时间长度
* @return
*/
public static String createJWT(
String id,
String subject,
long ttl
) {
long timeMillis = System.currentTimeMillis();//创建jwt时间
Date date = new Date(timeMillis); //转换为日期
JwtBuilder jwt = Jwts.builder()
.setId(id) //jwt_id
.setIssuedAt(date) //创建时间
.setSubject(subject) //sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串
.signWith(SignatureAlgorithm.HS256, generalKey());
//设置过期时间
if (ttl > 0) {
long exp = timeMillis + ttl; //过期时间
Date expDate = new Date(exp);
jwt.setExpiration(expDate);//设置过期时间
}
return jwt.compact();
}
/**
* 解密jwt
* @param jwt
* @return
*/
public static Claims parseJwt(String jwt)
{
SecretKey secretKey = generalKey();
Claims body = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt).getBody();
return body;
}
/**
* 获得subject,转化为json字符串
* @param user
* @return
*/
public static String generalSubject(User user)
{
return JSONObject.toJSONString(user);
}
/**
* 验证jwt
*/
public static CheckResult vaildateJwt(String jtw)
{
CheckResult res = new CheckResult();
Claims claims = null;
try{
claims = parseJwt(jtw);
res.setSuccess(true);
res.setClaims(claims);
}
catch (ExpiredJwtException e1) //过期异常
{
res.setSuccess(false);
res.setErrcode(Constant.JWT_ERRCODE_EXPIRE);
}
catch (SignatureException e2) //签名异常
{
res.setSuccess(false);
res.setErrcode(Constant.JWT_ERRCODE_FAIL);
}
catch (Exception e)
{
res.setSuccess(false);
res.setErrcode(Constant.JWT_ERRCODE_FAIL);
}
return res;
}
}拦截器:
package com.swq.jwt.config;
import com.swq.jwt.Interceptor.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* AJAX请求跨域
* @author Mr.W
* @time 2018-08-13
*/
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS)
.maxAge(3600);
}
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new interceptor())
.addPathPatterns("/**")//需要拦截的url
.excludePathPatterns("/user/login");//不需要拦截的url
}
}package com.swq.jwt.Interceptor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.swq.jwt.dto.CheckResult;
import com.swq.jwt.exception.TokenException;
import com.swq.jwt.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.apache.tomcat.jni.User;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if(token == null || token.equals(""))
{
throw new TokenException("token is null");
}
CheckResult checkResult = JwtUtil.vaildateJwt(token);
if(checkResult.isSuccess()) //验证成功
{
Claims claims = checkResult.getClaims();
String subject = claims.getSubject();
JSONObject parse = JSONObject.parseObject(subject);
User user = JSON.toJavaObject(parse, User.class);
return true;
}
else
{
throw new TokenException("token parse fail");
}
}
}Constant:
package com.swq.jwt.constant;
/**
* 常量类
*/
public class Constant {
//异常
public static final String JWT_ERRCODE_EXPIRE="token is expire";
public static final String JWT_ERRCODE_FAIL="unkonw error";
//jwt需要用到的常量
public static final String JWT_ID = "SWQ-1998"; //jwt签发者
//密匙
public static final String JWT_SECRET = "nfjenfaEINFUNSEFUNBFninwdw";//随便写个,注意长度必须大于16
//过期时间
public static final int JWT_TTL = 60 *60 *1000;
}前端封装axios:
//引入安装的axios插件
import axios from ‘axios‘
/****** 创建axios实例 ******/
const service = axios.create({
//baseURL: process.env.BASE_URL, // api的base_url
timeout: 5000 // 请求超时时间
});
service.interceptors.request.use(
config => {
if (sessionStorage.getItem(‘token‘)) { // 判断是否存在token,如果存在的话,则每个http header都加上token
config.headers.Authorization = sessionStorage.getItem(‘token‘);
}
return config;
},
err => {
return Promise.reject(err);
});
export default service登录成功后,后台返回token,前端保存
<template>
<div style="width:20%;margin:0 auto">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-input v-model="name" placeholder="请输入昵称"></el-input>
<p></p><p></p>
<el-input placeholder="请输入密码" v-model="password" show-password></el-input>
</div>
<p></p><p></p>
<el-button @click="login">登录</el-button>
</el-card>
</div>
</template>
<script>
import service from ‘@/request/http‘
export default {
data: function() {
return {
name:‘‘,
password: ‘‘
}
},
methods:{
login(){
service({
method:‘post‘,
url:‘/user/login‘,
data:{
name:this.name,
password:this.password
}
})
.then(res =>{
if(res.data.success == true)
{
sessionStorage.setItem(‘token‘,res.data.data) //保存token
//跳转到首页
this.$router.push(‘/index‘)//进入主页
}
else
{
this.$message.success(res.data.msg);
}
})
}
}
}
</script>