SpringBoot集成JWT(極簡版)

来源:https://www.cnblogs.com/b10100912/archive/2022/11/16/16895982.html
-Advertisement-
Play Games

##SpringBoot集成JWT(極簡版) ###在WebConfig配置類中設置介面統一首碼 import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.anno ...


SpringBoot集成JWT(極簡版)

在WebConfig配置類中設置介面統一首碼

import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements  WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 指定controller統一的介面首碼
        configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));
    }
}

導入JWT依賴

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

JWT工具類TokenUtils.java(生成token的工具類)

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.bai.entity.Admin;
import com.bai.service.AdminService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@Component
@Slf4j
public class TokenUtils {

    private static AdminService staticAdminService;

    @Resource
    private AdminService adminService;

    @PostConstruct
    public void setUserService() {
        staticAdminService = adminService;
    }

    /**
     * 生成token
     *
     * @return
     */
    public static String genToken(String adminId, String sign) {
        return JWT.create().withAudience(adminId) // 將 user id 保存到 token 裡面,作為載荷
                .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小時後token過期
                .sign(Algorithm.HMAC256(sign)); // 以 password 作為 token 的密鑰
    }

    /**
     * 獲取當前登錄的用戶信息
     *
     * @return user對象
     *  /admin?token=xxxx
     */
    public static Admin getCurrentAdmin() {
        String token = null;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getHeader("token");
            if (StrUtil.isNotBlank(token)) {
                token = request.getParameter("token");
            }
            if (StrUtil.isBlank(token)) {
                log.error("獲取當前登錄的token失敗, token: {}", token);
                return null;
            }
            String adminId = JWT.decode(token).getAudience().get(0);
            return staticAdminService.getById(Integer.valueOf(adminId));
        } catch (Exception e) {
            log.error("獲取當前登錄的管理員信息失敗, token={}", token,  e);
            return null;
        }
    }
}

攔截器JwtInterceptor.java


import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.bai.entity.Admin;
import com.bai.exception.ServiceException;
import com.bai.service.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Component
@Slf4j
public class LoginJWTInterceptor implements HandlerInterceptor {

    private static final String ERROR_CODE_401 = "401";

    @Autowired
    private AdminService adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        //這裡是判斷瀏覽器請求頭裡的token
        String token = request.getHeader("token");

        if (StrUtil.isBlank(token)) {
            token = request.getParameter("token");
        }

        // 執行認證
        if (StrUtil.isBlank(token)) {
            throw new ServiceException(ERROR_CODE_401, "無token,請重新登錄");
        }
        // 獲取 token 中的adminId
        String adminId;
        Admin admin;
        try {
            adminId = JWT.decode(token).getAudience().get(0);
            // 根據token中的userid查詢資料庫
            admin = adminService.getById(Integer.parseInt(adminId));
        } catch (Exception e) {
            String errMsg = "token驗證失敗,請重新登錄";
            log.error(errMsg + ", token=" + token, e);
            throw new ServiceException(ERROR_CODE_401, errMsg);
        }
        if (admin == null) {
            throw new ServiceException(ERROR_CODE_401, "用戶不存在,請重新登錄");
        }

        try {
            // 用戶密碼加簽驗證 token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(admin.getPassword())).build();
            jwtVerifier.verify(token); // 驗證token
        } catch (JWTVerificationException e) {
            throw new ServiceException(ERROR_CODE_401, "token驗證失敗,請重新登錄");
        }
        return true;
    }
}

在WebConfig配置類中添加自定義攔截器


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginJWTInterceptor loginJWTInterceptor;

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 指定controller統一的介面首碼
        configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));
    }

    // 加自定義攔截器JwtInterceptor,設置攔截規則
    //.excludePathPatterns("/api/admin/login");放開登錄介面,因為登錄的時候還沒有token
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginJWTInterceptor)  // 添加所有路徑需要校驗
                .addPathPatterns("/api/**").excludePathPatterns("/api/admin/login", "/api/admin/register");//不需要攔截的介面
    }

}

設置自定義頭配置(前端在request攔截器設置自定義頭)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;


@Configuration
public class CrosConfiguration {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 設置訪問源地址
        corsConfiguration.addAllowedHeader("*"); // 2 設置訪問源請求頭
        corsConfiguration.addAllowedMethod("*"); // 3 設置訪問源請求方法
        source.registerCorsConfiguration("/**", corsConfiguration); // 4 對介面配置跨域設置
        return new CorsFilter(source);
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • scanf在vs2022中是一個不安全的函數,vs自定義scanf_s是一個安全的函數,但是這在轉給其他編譯器可能不適用 我們可以在開頭加上一個#define _CRT_SECURE_NO_WARNINGS 1可以解決問題 但是自己打比較麻煩,這個時候我們可以打開vs編譯器的文件然後找到VC這個文件 ...
  • 平常是處理文字的時候更多用到的是字元串方面的工具類,作為學習漢字的工具,拼音還是很重要的一個輔助方式,分享一個漢字轉拼音的工具類。可以用於幫助學習漢字或者作為一些漢字的輔助說明都也是可以的。這個還支持將漢字拼音輸出為首字母,例如"愷龍"可以輸出為"kl",在現在大家很多時候都用縮寫的情況下,可以也可 ...
  • 1.HTTP是什麼? http是超文本傳輸協議用來在web瀏覽器和網站伺服器之間傳遞數據信息,http以明文的方式發送內容,不提供任何方式的數據加密,如果攻擊者截獲了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的信息,因此,HTTP協議不適合傳輸一些敏感信息,比如:信用卡號、密碼等支付 ...
  • 1、使用註解需要導入的依賴 1、1在application.xml文件中加入該約束 xmlns:context=http://www.springframework.org/schema/context http://www.springframework.org/schema/context ht ...
  • 我國目前並未出台專門針對網路爬蟲技術的法律規範,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥爬蟲普法”專欄,本欄目通過對真實案例的分析,旨在提高廣大爬蟲工程師的法律意識,知曉如何合法合規利用爬蟲技術,警鐘長鳴,做一個守法、護法、有原則的技術人員。 案情介紹 2018年1月至7月期間,咼某興 ...
  • 大家好,我是棧長。 今天給大家通報一則框架更新消息,時隔兩個月,Spring Cloud 2021.0.5 最新版發佈了,來看下最新的 Spring Cloud 版本情況: Spring Cloud 無疑是現在 Java 微服務事實上的標準,完全基於 Spring Boot 構建,依賴 Spring ...
  • 目錄 一.freeglut 簡介 二.freeglut 下載 五.猜你喜歡 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效 零基礎 ...
  • 類模板=>實力化=>模板類 通過類模板實現棧,點擊查看代碼 #include <iostream> #include <cstring> using namespace std; template<typename T> //template<typename T=int> 也可以這樣寫,寫個預設類 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...