Spring Boot OAuth 2.0 客戶端


在上一篇《OAuth 2.0 授權碼請求》中我們已經可以獲取到access_token了,本節將使用客戶端來訪問遠程資源

配置資源服務器

授權服務器負責生成並發放訪問令牌(access_token),客戶端在訪問受保護的資源時會帶上訪問令牌,資源服務器需要解析並驗證客戶端帶的這個訪問令牌。

如果你的資源服務器同時也是一個授權服務器(資源服務器和授權服務器在一起),那么資源服務器就不需要考慮令牌解析的事情了,否則這一步是不可或缺的。

To use the access token you need a Resource Server (which can be the same as the Authorization Server). Creating a Resource Server is easy, just add @EnableResourceServer and provide some configuration to allow the server to decode access tokens. If your application is also an Authorization Server it already knows how to decode tokens, so there is nothing else to do. If your app is a standalone service then you need to give it some more configuration.

同時,把它們放在一起的話還有一個問題需要注意,我們知道過濾器是順序執行的,因此需要確保那些通過訪問令牌來訪問的資源路徑不能被主過濾攔下了,需要單獨摘出來。

Note: if your Authorization Server is also a Resource Server then there is another security filter chain with lower priority controlling the API resources. Fo those requests to be protected by access tokens you need their paths not to be matched by the ones in the main user-facing filter chain, so be sure to include a request matcher that picks out only non-API resources in the WebSecurityConfigurer above.

關於Spring Security中過濾器的順序可以參見 

https://docs.spring.io/spring-security/site/docs/5.0.6.RELEASE/reference/htmlsingle/#filter-ordering

這里偷個懶將它們放在一起:

package com.cjs.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        super.configure(resources);
    }

    /**
     * 用於配置對受保護的資源的訪問規則
     * 默認情況下所有不在/oauth/**下的資源都是受保護的資源
     * {@link OAuth2WebSecurityExpressionHandler}
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.requestMatchers().antMatchers("/haha/**")
                .and()
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

這里配置很簡潔,很多都用了默認的設置(比如:resourceId,accessDeniedHandler,sessionManagement等等,具體可參見源碼)

接下來,看看本例中我們被保護的資源,簡單的幾個資源(都以/haha開頭),只為測試:

package com.cjs.example.controller;

import com.cjs.example.domain.UserInfo;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

@RestController
@RequestMapping("/haha")
public class MainController {

    @GetMapping("/sayHello")
    public String sayHello(String name) {
        return "Hello, " + name;
    }

    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping("/sayHi")
    public String sayHi() {
        return "hahaha";
    }

    @RequestMapping("/userInfo")
    public UserInfo userInfo(Principal principal) {
        UserInfo userInfo = new UserInfo();
        userInfo.setName(principal.getName());
        return userInfo;
    }
}

授權服務器配置

package com.cjs.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;


@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private RedisConnectionFactory connectionFactory;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        super.configure(security);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("my-client-1")
                .secret("$2a$10$0jyHr4rGRdQw.X9mrLkVROdQI8.qnWJ1Sl8ly.yzK0bp06aaAkL9W")
                .authorizedGrantTypes("authorization_code", "refresh_token")
                .scopes("read", "write", "execute")
                .redirectUris("http://localhost:8081/login/oauth2/code/callback");
//                .redirectUris("http://www.baidu.com");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore());
    }

    @Bean
    public TokenStore tokenStore() {
        return new RedisTokenStore(connectionFactory);
    }


    public static void main(String[] args) {
        System.out.println(new org.apache.tomcat.util.codec.binary.Base64().encodeAsString("my-client-1:12345678".getBytes()));
        System.out.println(java.util.Base64.getEncoder().encodeToString("my-client-1:12345678".getBytes()));
    }
}

和之前相比,我們增加了TokenStore,將Token存儲到Redis中。否則默認放在內存中的話每次重啟的話token都丟了。下面是一個例子:

application.yml如下:

server:
  port: 8080

spring:
  redis:
    host: 127.0.0.1
    port: 6379

logging:
  level:
    root: debug
    org.springframework.web: debug
    org.springframework.security: debug

WebSecurity配置

我們有了資源,有了授權,我們還缺少用戶。WebSecurity主要是配置咱們這個項目的一些安全配置,比如用戶、認證、授權等等。

package com.cjs.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("zhangsan")
                .password("$2a$10$qsJ/Oy1RmUxFA.YtDT8RJ.Y2kU3U4z0jvd35YmiMOAPpD.nZUIRMC")
                .roles("USER")
                .and()
                .withUser("lisi")
                .password("$2a$10$qsJ/Oy1RmUxFA.YtDT8RJ.Y2kU3U4z0jvd35YmiMOAPpD.nZUIRMC")
                .roles("USER", "ADMIN");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**", "/plugins/**", "/favicon.ico");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        System.out.println(bCryptPasswordEncoder.encode("123456"));
        System.out.println(bCryptPasswordEncoder.encode("12345678"));
    }
}

這里多說兩句,關於Endpoint和HttpSecurity

Endpoint

有很多端點我們是可以重寫的,比如:/login,/oauth/token等等

HttpSecurity

很多初學者可能會不知道怎么配置HttpSecurity,這個時候其實最好的方法就是看代碼或者API文檔

下面一起看一下常見的幾個配置

我們先來看一下,當我們繼承WebSecurityConfigurerAdapter之后它的默認的HttpSecurity是怎么配置的:

// @formatter:off
    protected void configure(HttpSecurity http) throws Exception {
        logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin().and()
            .httpBasic();
    }
    // @formatter:on

可以看到,所有的請求都需要授權,並且指定登錄的uri是/login,同時支持Basic認證。

requestMatchers()

這個方法是用於限定只有特定的HttpServletRequest實例才會導致該HttpSecurity被調用,當然是通過請求uri進行限定的了。它后面可以接多個匹配規則。例如:

@Configuration
@EnableWebSecurity
public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http
                        .requestMatchers()
                                .antMatchers("/api/**")
                                .antMatchers("/oauth/**")
                                .and()
                        .authorizeRequests()
                                .antMatchers("/**").hasRole("USER")
                                .and()
                        .httpBasic();
        }
        
    /*  與上面那段等價
        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http
                        .requestMatchers()
                                .antMatchers("/api/**")
                                .and()
                         .requestMatchers()
                                .antMatchers("/oauth/**")
                                .and()
                        .authorizeRequests()
                                .antMatchers("/**").hasRole("USER")
                                .and()
                        .httpBasic();
        }
    */

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth
                        .inMemoryAuthentication()
                                .withUser("user").password("password").roles("USER");
        }
}

formLogin()

該方法是用於配置登錄相關的設置的。例如:

 @Configuration
 @EnableWebSecurity
 public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
                                .usernameParameter("username") // default is username
                                .passwordParameter("password") // default is password
                                .loginPage("/authentication/login") // default is /login with an HTTP get
                                .failureUrl("/authentication/login?failed") // default is /login?error
                                .loginProcessingUrl("/authentication/login/process"); // default is /login
                                                                                                      
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
        }
 }

當我們沒有配置登錄的時候,會用默認的登錄,有默認的登錄頁面,還有好多默認的登錄配置。具體可參見 FormLoginConfigurer.loginPage(String)方法

authorizeRequests()

該方法允許基於HttpServletRequest進行訪問限制,比如角色、權限。例如:

 @Configuration
 @EnableWebSecurity
 public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN")
                                .antMatchers("/**").hasRole("USER").and().formLogin();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
                                .and().withUser("admin").password("password").roles("ADMIN", "USER");
        }
 }

anyRequest()表示匹配任意請求
authenticated()表示只有認證通過的用戶才可以訪問

更多可以參見API文檔:https://docs.spring.io/spring-security/site/docs/5.0.6.RELEASE/api/

用Postman訪問資源

獲取授權碼

在瀏覽器中輸入http://localhost:8080/oauth/authorize?response_type=code&client_id=my-client-1&redirect_uri=http://www.baidu.com&scope=read

然后跳到登錄頁面,輸入用戶名和密碼登錄,然后從重定向url中拿到code

換取訪問令牌

訪問資源

http://localhost:8080/haha/sayHi?access_token=9f908b8f-06d6-4987-b105-665ca5a4522a

{
    "error": "access_denied",
    "error_description": "不允許訪問"
}
這里不允許訪問是因為我用zhangsan登錄的,他不在ADMIN角色中

http://localhost:8080/haha/userInfo?access_token=9f908b8f-06d6-4987-b105-665ca5a4522a

{
    "name": "zhangsan"
}


http://localhost:8080/haha/sayHello?name=jack&access_token=9f908b8f-06d6-4987-b105-665ca5a4522a

Hello, jack

通過客戶端程序訪問資源

訪問GitHub

參照SpringBoot官網的示例

https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-oauth2-client

https://github.com/spring-projects

https://github.com/spring-projects/spring-boot

可以將代碼拷下來 https://github.com/spring-projects/spring-boot.git

第一步  將我們的客戶端注冊到GitHub上去

GitHub的OAuth文檔在這里  https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

第二步  瀏覽器輸入http://localhost:8080/后出現如下界面

第三步  點擊任意一個連接,跳GitHub登錄

授權以后就可以重定向到我們的localhost:8080/了

主要配置如下:

APP-CLIENT-ID: 7e304109d91ed8e9bf72
APP-CLIENT-SECRET: 003daa47fa0f350d181c8741d8bac6833aef568a

spring:
  security:
    oauth2:
      client:
        registration:
          github-client-1:
            client-id: ${APP-CLIENT-ID}
            client-secret: ${APP-CLIENT-SECRET}
            client-name: Github user
            provider: github
            scope: user
            redirect-uri-template: http://cjshuashengke.6655.la:11664/login/oauth2/code/github
          github-client-2:
            client-id: ${APP-CLIENT-ID}
            client-secret: ${APP-CLIENT-SECRET}
            client-name: Github email
            provider: github
            scope: user:email
            redirect-uri-template: http://cjshuashengke.6655.la:11664/login/oauth2/code/github

pom.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>sample.oauth2.client</groupId>
    <artifactId>spring-boot-sample-oauth2-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- Compile -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>
        <!-- Test -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

啟動類

package sample.oauth2.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleOAuth2ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleOAuth2ClientApplication.class);
    }

}

ExampleController

package sample.oauth2.client;

import java.security.Principal;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExampleController {

    @RequestMapping("/")
    public String email(Principal principal) {
        return "Hello " + principal.getName();
    }

}

訪問自定義的Provider

在這里我遇到一些問題,將provider換成自己的localhost:8080就總是報錯,不知道什么原因。

想想還是寫出來吧,希望有大神看到幫我指點迷津。。。

 

首先需要明確一點:Spring Security OAuth2提供了一套客戶端實現,Spring Boot也有它自己的方式。

這里我是按照Spring Boot的那一套來的

Spring Boot最大的優點莫過於自動配置了

只要在你的classpath下有spring-security-oauth2-client,那么將會自動配置OAuth2 Client。

配置的屬性用的是OAuth2ClientProperties

具體參見 https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/#boot-features-security-oauth2

例如:

默認情況下,Spring Security的OAuth2LoginAuthenticationFilter只處理URL匹配/login/oauth2/code/*的請求。

如果你想自定義redirect-uri-template可以在WebSecurityConfigurerAdapter中配置。例如:

public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
      .anyRequest().authenticated()
      .and()
      .oauth2Login()
      .redirectionEndpoint()
      .baseUri("/custom-callback");
  }
}

其實,不僅僅可以自定義重定向端點,其它的比如授權端點也是可以自定義的,可參見源碼

 

下面重點說下我的配置

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cjs.example</groupId>
    <artifactId>cjs-oauth2-code-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cjs-oauth2-code-client</name>
    <description></description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

application.yml

server:
  port: 8081

spring:
  security:
    oauth2:
      client:
        registration:
          my-client-1:
            client-id: my-client-1
            client-secret: 12345678
            client-name: ABC
            provider: my-oauth-provider
            scope: read
            redirect-uri-template: http://localhost:8081/login/oauth2/code/callback
            client-authentication-method: basic
            authorization-grant-type: authorization_code
        provider:
          my-oauth-provider:
            authorization-uri: http://localhost:8080/oauth/authorize
            token-uri: http://localhost:8080/oauth/token
logging:
  level:
    root: debug

分別啟動兩個項目

瀏覽器輸入http://localhost:8080/test

點擊鏈接ABC

輸入zhangsan/123456,結果報錯了

查看控制台錯誤信息

org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found] 
	at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:146)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
	at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:128)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]

打端點,發現重定向過來的HttpServletRequest中session=null

正常情況下session不應該是null,而且屬性中還應該有一個key為org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository.AUTHORIZATION_REQUEST的屬性的

 

后來看根據Spring Security那一套說用@EnableOAuth2Client

利用OAuth2RestTemplate來訪問資源,具體參見《Spring Security OAuth 2.0

但是我發現加了這些問題依舊,根本問題是服務端帶着code重定向到客戶端的時候就失敗了

在客戶端收到的重定向請求中session為null

不知道大家有沒有遇到這種問題,求路過的大神們支招。。。

下面貼出客戶端完整代碼

package com.cjs.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.security.Principal;

@Controller
public class MainController {

    @Autowired
    private OAuth2RestTemplate oAuth2RestTemplate;

    @GetMapping("/test")
    public String test(Principal principal) {
        return "Hello, " + principal.getName();
    }

    @GetMapping("/hello")
    public String hello() {
        return oAuth2RestTemplate.getForObject("http://localhost:8080/sayHi", String.class);
    }
}
package com.cjs.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;

@EnableOAuth2Client
@SpringBootApplication
public class CjsOauth2CodeClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(CjsOauth2CodeClientApplication.class, args);
    }

    @Autowired
    private OAuth2ClientContext oauth2ClientContext;

    @Bean
     public OAuth2RestTemplate restTemplate() {
         return new OAuth2RestTemplate(new AuthorizationCodeResourceDetails(), oauth2ClientContext);
     }
}

工程截圖

 

代碼上傳至 https://github.com/chengjiansheng/cjs-oauth2-example.git

參考

https://docs.spring.io/spring-security-oauth2-boot/docs/2.0.1.RELEASE/reference/pdf/spring-security-oauth2-boot-reference.pdf

https://docs.spring.io/spring-security/site/docs/5.0.6.RELEASE/reference/htmlsingle/#oauth2login-advanced-login-page

https://docs.spring.io/spring-security/site/docs/5.0.6.RELEASE/api/

https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples

https://segmentfault.com/a/1190000012309216

https://www.jianshu.com/p/bf5dd33aea6d?utm_source=oschina-app

https://www.aliyun.com/jiaocheng/800606.html

https://blog.csdn.net/peter1220/article/details/52413250

https://blog.csdn.net/weixin_42033269/article/details/80086422

 


免責聲明!

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



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