Spring Boot OAuth 2.0 客戶端

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

配置資源服務器

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

若是你的資源服務器同時也是一個受權服務器(資源服務器和受權服務器在一塊兒),那麼資源服務器就不須要考慮令牌解析的事情了,不然這一步是不可或缺的。java

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.git

同時,把它們放在一塊兒的話還有一個問題須要注意,咱們知道過濾器是順序執行的,所以須要確保那些經過訪問令牌來訪問的資源路徑不能被主過濾攔下了,須要單獨摘出來。github

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.web

關於Spring Security中過濾器的順序能夠參見 redis

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

這裏偷個懶將它們放在一塊兒:express

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等等,具體可參見源碼)apache

接下來,看看本例中咱們被保護的資源,簡單的幾個資源(都以/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

http://www.javashuo.com/article/p-myfdxwel-mh.html

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

相關文章
相關標籤/搜索