JWT - 通過Axios攔截器完成Token轉發實現單點登錄

前端部分

需要將token字符串用戶信息存入的Cookie中,因此需要引入js-cookie。前端採用axios發送請求,所以還需要引入axios

1、封裝axios

創建一個request.js文件,用來封裝axios

import axios from 'axios';  // 引入axios
import cookie from 'js-cookie';  // 引入js-cookie

// 創建axios實例
const service = axios.create({
	baseURL:'http://localhost:9000',   // 請求地址,可以使用nginx代理
	timeout:20000					   // 請求超時時間
});

// 配置request攔截器
service.interceptors.request.use(
	config => {
	    // 如果Cookie中存在這個token,就在header中設置這個token
	    // 這樣token就可以跨域轉發
		if(cookie.get('user_token')){
			config.headers['token'] = cookie.get('user_token');
		}
		return config;
	},
	err => {  // 出錯調用
		return Promise.reject(err);
	}
)
export default service;

2、定製API - login.js

定製登錄的方法。

import request from '@/utils/request';  // 引入request.js
export default {
    /**
     * 登錄的方法
     * @param userInfo 用戶登錄信息
     */
	submitLogin(userInfo){
		return request({
			// 登錄的請求地址,完整即http://localhost:9000/user/login
			url:'/user/login',  
			method:'post',   // 請求方式
			data:userInfo    // 請求信息
		});
	}
}

3、完成登錄 - 基於Vue和Axios發送請求

import cookie from 'js-cookie'
import loginApi from '@/api/login'

export default{
	data(){
		return {
			user:{
				mobile:'',    // 手機/賬號
				password:'',  // 密碼
			},
			loginInfo:{},     // 登錄用戶信息
		}
	},
	methods:{
		/**
		 * 登錄按鈕調用的方法
		 */
		submitLogin(){
			/**
			 * 調用登錄API
			 */
			loginApi.submitLogin(this.user)
				.then(response => {
				    // 將服務端傳過來的token字符串存入cookie
					cookie.set('user_token',response.data.data.token,{domain:'localhsot'});
					// 這裏就可以調用方法去獲取用戶信息並存入Cookie了
					// 方法就不再定義了,直接使用,定義方式與前面一致
					// 因爲在request.js中制定了攔截器,會檢查token是否存在,存在就跟着header信息一起被傳走
					loginApi.getLoginUserInfo()
						.then(response => {
							this.loginInfo = response.data.data.userInfo;
							// 將獲取到的用戶信息存入到cookie中,其他頁面從cookie中取
							cookie.set('user_info',this.loginInfo,{domain:'localhost'});
							// 跳轉到首頁 - 也可以使用路由跳轉
							// 首頁就可以從cookie中獲取了
							window.location.href = "/";
						})
				})
		}
	}
}

4、登錄成功,信息獲取

在cookie中獲取信息,通過JSON.parse方法將其轉換爲JSON對象。

後端部分

1、要使用JWT,需要引入JWT的依賴

<!-- JWT-->
<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt</artifactId>
	<version>0.7.0</version>
</dependency>

2、創建JWT幫助類

public class JwtUtils {

    // 常量
    public static final long EXPIRE = 1000 * 60 * 60 * 24; // token過期時間
    public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; // 祕鑰

    // 生成token字符串的方法
    public static String getJwtToken(String id, String nickname){
        String JwtToken = Jwts.builder()
                // 頭信息
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                .setSubject("guli-user")   // 分類
                // 設置過期時間
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                // 設置Token主體部分,存儲用戶信息
                .claim("id", id)
                .claim("nickname", nickname)


                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }

    /**
     * 判斷token是否存在與有效
     * @param jwtToken
     * @return
     */
    public static boolean checkToken(String jwtToken) {
        if(StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判斷token是否存在與有效
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根據token字符串獲取id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }
}

3、驗證用戶登錄成功之後生成Token字符串

String jwtToken = JwtUtils.getJwtToken(user.getId(),user.getNickname());

4、根據token信息獲取用戶信息

前面前端部分說了,每次請求的時候,都會將token信息放入header,這樣就可以跨域(cookie無法跨域)。
要獲取用戶信息,則需要通過這個token信息來確定,使用jwt幫助類中的getMemberIdByJwtToken方法來獲取。

    /**
     * 根據token字符串獲取id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }

獲取到id,我們就可以通過這個id去獲取用戶信息。

@GetMapping("/getUserInfo")
public R getMemberInfo(HttpServletRequest request){
	String userId = JwtUtils.getMemberIdByJwtToken(request);
	User user= userService.getById(userId);
	return R.ok().data("userInfo",user);
}

到此爲止,完成了一個簡單的token跨域驗證。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章