簡體   English   中英

API 網關中的 OAuth 問題

[英]OAuth issue in API gateway

I am facing the OAuth issue, details are below: I am having two microservices: registration-service( https://github.com/choudharylakshyaveer/registration-service ) student-service( https://github.com/choudharylakshyaveer/student -服務

For these two I have added: cloud-config-server( https://github.com/choudharylakshyaveer/cloud-config-server ) naminig-server( https://github.com/choudharylakshyaveer/naming-server ) gateway( https ://github.com/choudharylakshyaveer/api-gateway

前端:在反應 js: https://github.com/choudharylakshyaveer/chargie

第一次使用,需要注冊一個新用戶,可以從 curl 完成:

curl --location --request GET 'http://localhost:8765/user/save' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "user@chargie.com",
    "password": "chaudhary22",
    "enabled": true,
    "roles": [
        "ROLE_ADMIN",
        "ROLE_USER"
    ]
}'

要使用上述注冊用戶登錄,可以從 cUrl 運行以下命令:

curl --location --request POST 'http://localhost:8765/login' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "user@chargie.com",
    "password": "chaudhary22"
}'

Once I log In and get the Bearer token, after that I am facing cors issue from the reactJs FE, bu same request is working fine from the Postman, below is request from postman:

curl --location --request GET 'http://localhost:8765/REGISTRATION-SERVICE/test' \
--header 'Access-Control-Allow-Credentials: true' \
--header 'Access-Control-Allow-Headers: content-type' \
--header 'Access-Control-Allow-Methods: PUT, POST, GET, DELETE, PATCH, OPTIONS' \
--header 'Access-Control-Allow-Origin: *' \
--header 'Access-Control-Max-Age: 1800' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJyb2xlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwic3ViIjoibHZzIiwiaWF0IjoxNjU4OTM0NzIxLCJleHAiOjE2NTg5NjM1MjF9.MN6lCrwLB2bBDBLp-HG4nlSRlyhoR2cQDSRGvJCD2WwDMojhei0wW7xVuDwVCtRUANK02aQMhqagafB2csDWWg'

以下是用於從 ReactJs FE 發出請求的代碼:

var config = {
            method: 'get',
            url: 'http://localhost:8765/REGISTRATION-SERVICE/test',
            headers: { 
              Authorization: `Bearer ${token}`,
              'Content-Type': 'application/json',
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Credentials': 'true',
              'Access-Control-Max-Age': '1800',
              'Access-Control-Allow-Headers': 'content-type',
              'Access-Control-Allow-Methods': 'PUT, POST, GET, DELETE, PATCH, OPTIONS'
            },
            Authorization: `Bearer ${token}`
          };
          
          axios(config)
          .then(function (response) {
            console.log(JSON.stringify(response.data));
          })
          .catch(function (error) {
            console.log(error);
          });

這個請求給了我 CORS 問題: 在此處輸入圖像描述

api-gateway 的 SecurityContextRepository class 中使用的 ServerSecurityContextRepository 的重寫方法的片段:

@Override
    public Mono<SecurityContext> load(ServerWebExchange swe) {
        ServerHttpRequest request = swe.getRequest();
        HttpHeaders headers = request.getHeaders();
        String authHeader = headers.getFirst(HttpHeaders.AUTHORIZATION);

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.authenticationManager.authenticate(auth).map((authentication) -> {
                return new SecurityContextImpl(authentication);
            });
        } else {
            return Mono.empty();
        }
    }

在這里,當請求來自 Postman 時,下面是headers變量中的接收:

[access-control-allow-credentials:"true", access-control-allow-headers:"content-type", access-control-allow-methods:"PUT, POST, GET, DELETE, PATCH, OPTIONS", access-control-allow-origin:"*", access-control-max-age:"1800", authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJyb2xlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwic3ViIjoibHZzIiwiaWF0IjoxNjU4OTM0NzIxLCJleHAiOjE2NTg5NjM1MjF9.MN6lCrwLB2bBDBLp-HG4nlSRlyhoR2cQDSRGvJCD2WwDMojhei0wW7xVuDwVCtRUANK02aQMhqagafB2csDWWg", user-agent:"PostmanRuntime/7.29.0", accept:"*/*", postman-token:"6c0d7a9a-dcde-45d7-8422-1476682db9f4", host:"localhost:8765", accept-encoding:"gzip, deflate, br", connection:"keep-alive"]

但是當相同的請求來自前端時,下面會在headers變量中收到,並且它似乎格式不正確:

[host:"localhost:8765", connection:"keep-alive", pragma:"no-cache", cache-control:"no-cache", accept:"*/*", access-control-request-method:"GET", access-control-request-headers:"access-control-allow-credentials,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,access-control-max-age,authorization", origin:"http://localhost:3000", user-agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", sec-fetch-mode:"cors", sec-fetch-site:"same-site", sec-fetch-dest:"empty", referer:"http://localhost:3000/", accept-encoding:"gzip, deflate, br", accept-language:"en-US,en;q=0.9"]

因此,在這里我沒有在后端的headers變量上收到正確的授權 header,以便我可以使用 Bearer 令牌來驗證它。

添加cors后工作,SecurityWebFilterChain方法的完整代碼如下:

http
            .exceptionHandling()
            .authenticationEntryPoint((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                });
            }).accessDeniedHandler((swe, e) -> {
                return Mono.fromRunnable(() -> {
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                });
            }).and()
            .cors().configurationSource(request -> {
                CorsConfiguration config = new CorsConfiguration();
                config.setAllowedOrigins(Collections.singletonList("*"));
                config.setAllowedMethods(Arrays.asList("GET","POST","PUT","PATCH", "DELETE","OPTIONS"));
                config.setAllowedHeaders(Collections.singletonList("*"));
                return config;
            })
            .and()
            .csrf().disable()
            .and()
            .formLogin().disable()
            .httpBasic().disable()
            .authenticationManager(authenticationManager)
            .securityContextRepository(securityContextRepository)
            .authorizeExchange()
            .pathMatchers("/login").permitAll()
            .pathMatchers("/user/save").permitAll() //line added
            .anyExchange()
            .authenticated()
            
            .and().build();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM