微服務網關6-網關鑒權


一、網關鑒權

1、問題

當我們在未登錄狀態下點擊“購買課程”按鈕時,會顯示“未知錯誤”,查看trade微服務控制台,發現控制台中報錯,提示JWT為空,無法鑒權。

B0aKe0.png

2、解決方案

微服務網關中添加自定義全局過濾器,統一處理需要鑒權的服務

3、鑒權邏輯描述

  1. 當客戶端第一次請求服務時,服務端對用戶進行信息認證(登錄)
  2. 認證通過,將用戶信息進行加密形成token,返回給客戶端
  3. 作為登錄憑證以后每次請求,客戶端都攜帶認證的token
  4. 服務端對token進行解密,判斷是否有效

B0d91J.png

對於驗證用戶是否已經登錄鑒權的過程可以在網關統一檢驗。檢驗的標准就是請求中是否攜帶token憑證以及token的正確性。

下面的我們自定義一個GlobalFilter,去校驗所有的請求參數中是否包含“token”,如何不包含請求

參數“token”則不轉發路由,否則執行正常的邏輯。

二、開發鑒權邏輯

1、網關中添加依賴

 <dependency>
     <groupId>com.atguigu</groupId>
     <artifactId>common_util</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <!--排除spring-boot-starter-web,否則和gateway中的webflux沖突-->
     <exclusions>
         <exclusion>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </exclusion>
     </exclusions>
</dependency>

<!--將隨着spring-boot-starter-web排除的servlet-api添加回來 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

<!--gson-->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>

2、排除數據源自動配置

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

3、創建過濾器

package com.atguigu.guli.infrastructure.apigateway.filter;

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
    
        //谷粒學院api接口,校驗用戶必須登錄
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        if(antPathMatcher.match("/api/**/auth/**", path)) {
            List<String> tokenList = request.getHeaders().get("token");
    
            //沒有token
            if(null == tokenList) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            }
    
            //token校驗失敗
            Boolean isCheck = JwtUtils.checkJwtTToken(tokenList.get(0));
            if(!isCheck) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            }
        }
    
        //放行
        return chain.filter(exchange);
    }
    
    //定義當前過濾器的優先級,值越小,優先級越高
    @Override
    public int getOrder() {
        return 0;
    }
    
    private Mono<Void> out(ServerHttpResponse response) {
    
        JsonObject message = new JsonObject();
        message.addProperty("success", false);
        message.addProperty("code", 28004);
        message.addProperty("data", "");
        message.addProperty("message", "鑒權失敗");
        byte[] bytes = message.toString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        //指定編碼,否則在瀏覽器中會中文亂碼
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        //輸出http響應
        return response.writeWith(Mono.just(buffer));
    }
}

測試:在未登錄狀態下點擊立即購買顯示“鑒權失敗”。

B0dehD.jpg

4、前端修改

guli-site的utils/request.js中修改響應過濾器 ,添加分支:

else if (res.code === 28004) { // 鑒權失敗
    window.location.href = '/login'
    return
} 

修改pages/login.vue的submitLogin方法:登錄后回到原來的頁面

// 跳轉到首頁
// window.location.href = '/'
if (document.referrer.indexOf('register') !== -1) {
    window.location.href = '/'
} else {
    history.go(-1)
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM