Spring Cloud入門-Oauth2授權之基於JWT完成單點登錄(Hoxton版本)

項目使用的Spring Cloud爲Hoxton版本,Spring Boot爲2.2.2.RELEASE版本

Spring Cloud入門系列彙總

序號 內容 鏈接地址
1 Spring Cloud入門-十分鐘瞭解Spring Cloud https://blog.csdn.net/ThinkWon/article/details/103715146
2 Spring Cloud入門-Eureka服務註冊與發現(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103726655
3 Spring Cloud入門-Ribbon服務消費者(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103729080
4 Spring Cloud入門-Hystrix斷路器(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103732497
5 Spring Cloud入門-Hystrix Dashboard與Turbine斷路器監控(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103734664
6 Spring Cloud入門-OpenFeign服務消費者(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103735751
7 Spring Cloud入門-Zuul服務網關(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103738851
8 Spring Cloud入門-Config分佈式配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103739628
9 Spring Cloud入門-Bus消息總線(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103753372
10 Spring Cloud入門-Sleuth服務鏈路跟蹤(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103753896
11 Spring Cloud入門-Consul服務註冊發現與配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103756139
12 Spring Cloud入門-Gateway服務網關(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103757927
13 Spring Cloud入門-Admin服務監控中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103758697
14 Spring Cloud入門-Oauth2授權的使用(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103761687
15 Spring Cloud入門-Oauth2授權之JWT集成(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103763364
16 Spring Cloud入門-Oauth2授權之基於JWT完成單點登錄(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103766368
17 Spring Cloud入門-Nacos實現註冊和配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103769680
18 Spring Cloud入門-Sentinel實現服務限流、熔斷與降級(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103770879
19 Spring Cloud入門-Seata處理分佈式事務問題(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103786102
20 Spring Cloud入門-彙總篇(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103786588

摘要

Spring Cloud Security 爲構建安全的SpringBoot應用提供了一系列解決方案,結合Oauth2可以實現單點登錄功能,本文將對其單點登錄用法進行詳細介紹。

單點登錄簡介

單點登錄(Single Sign On)指的是當有多個系統需要登錄時,用戶只需登錄一個系統,就可以訪問其他需要登錄的系統而無需登錄。

創建oauth2-client模塊

這裏我們創建一個oauth2-client服務作爲需要登錄的客戶端服務,使用上一節中的oauth2-jwt-server服務作爲授權服務,當我們在oauth2-jwt-server服務上登錄以後,就可以直接訪問oauth2-client需要登錄的接口,來演示下單點登錄功能。

在pom.xml中添加相關依賴:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-security</artifactId>
</dependency>

在application.yml中進行配置:

server:
  port: 9501
  servlet:
    session:
      cookie:
        # 防止cookie衝突,衝突會導致登錄驗證不通過
        name: OAUTH2-CLIENT-SESSIONID

oauth2-service-url: http://localhost:9401

spring:
  application:
    name: oauth2-client

security:
  # 與oauth2-server對應的配置
  oauth2:
    client:
      client-id: admin
      client-secret: admin123456
      user-authorization-uri: ${oauth2-service-url}/oauth/authorize
      access-token-uri: ${oauth2-service-url}/oauth/token
    resource:
      jwt:
        key-uri: ${oauth2-service-url}/oauth/token_key

在啓動類上添加@EnableOAuth2Sso註解來啓用單點登錄功能:

@EnableOAuth2Sso
@SpringBootApplication
public class Oauth2ClientApplication {

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

}

添加接口用於獲取當前登錄用戶信息:

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/getCurrentUser")
    public Object getCurrentUser(Authentication authentication) {
        return authentication;
    }

}

修改授權服務器配置

修改oauth2-jwt-server模塊中的AuthorizationServerConfig類,將綁定的跳轉路徑爲http://localhost:9501/login,並添加獲取祕鑰時的身份認證。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    //以上省略一堆代碼...
    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                // 配置client_id
                .withClient("admin")
                // 配置client_secret
                .secret(passwordEncoder.encode("admin123456"))
                // 配置訪問token的有效期
                .accessTokenValiditySeconds(3600)
                // 配置刷新token的有效期
                .refreshTokenValiditySeconds(864000)
                // 配置redirect_uri,用於授權成功後的跳轉
                // .redirectUris("http://www.baidu.com")
                // 單點登錄時配置
                .redirectUris("http://localhost:9501/login")
                // 自動授權配置
                // .autoApprove(true)
                // 配置申請的權限範圍
                .scopes("all")
                // 配置grant_type,表示授權類型
                .authorizedGrantTypes("authorization_code", "password", "refresh_token");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 獲取密鑰需要身份認證,使用單點登錄時必須配置
        security.tokenKeyAccess("isAuthenticated()");
    }
}

網頁單點登錄演示

啓動oauth2-client服務和oauth2-jwt-server服務;

訪問客戶端需要授權的接口http://localhost:9501/user/getCurrentUser會跳轉到授權服務的登錄界面;

在這裏插入圖片描述

進行登錄操作後跳轉到授權頁面;

在這裏插入圖片描述

授權後會跳轉到原來需要權限的接口地址,展示登錄用戶信息;

在這裏插入圖片描述

如果需要跳過授權操作進行自動授權可以添加autoApprove(true)配置:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    //以上省略一堆代碼...
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                // 配置client_id
                .withClient("admin")
                // 配置client_secret
                .secret(passwordEncoder.encode("admin123456"))
                // 配置訪問token的有效期
                .accessTokenValiditySeconds(3600)
                // 配置刷新token的有效期
                .refreshTokenValiditySeconds(864000)
                // 配置redirect_uri,用於授權成功後的跳轉
                // .redirectUris("http://www.baidu.com")
                // 單點登錄時配置
                .redirectUris("http://localhost:9501/login")
                // 自動授權配置
                .autoApprove(true)
                // 配置申請的權限範圍
                .scopes("all")
                // 配置grant_type,表示授權類型
                .authorizedGrantTypes("authorization_code", "password", "refresh_token");
    }
}

調用接口單點登錄演示

這裏我們使用Postman來演示下如何使用正確的方式調用需要登錄的客戶端接口。

訪問客戶端需要登錄的接口:http://localhost:9501/user/getCurrentUser

使用Oauth2認證方式獲取訪問令牌:

在這裏插入圖片描述

輸入獲取訪問令牌的相關信息,點擊請求令牌:

在這裏插入圖片描述

此時會跳轉到授權服務器進行登錄操作:

在這裏插入圖片描述

登錄成功後使用獲取到的令牌:

在這裏插入圖片描述

最後請求接口可以獲取到如下信息:

{
	"authorities": [{
		"authority": "admin"
	}],
	"details": {
		"remoteAddress": "0:0:0:0:0:0:0:1",
		"sessionId": "6F5A553BB678C7272145FF9FF2A5D8F4",
		"tokenValue": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJqb3Vyd29uIiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTU3NzY4OTc2NiwiYXV0aG9yaXRpZXMiOlsiYWRtaW4iXSwianRpIjoiZjAwYjVkMGUtNjFkYi00YjBmLTkyNTMtOWQxZDYwOWM4ZWZmIiwiY2xpZW50X2lkIjoiYWRtaW4iLCJlbmhhbmNlIjoiZW5oYW5jZSBpbmZvIn0.zdgFTWJt3DnAsjpQRU6rNA_iM7gVHX7E9bCyF73MOSM",
		"tokenType": "bearer",
		"decodedDetails": null
	},
	"authenticated": true,
	"userAuthentication": {
		"authorities": [{
			"authority": "admin"
		}],
		"details": null,
		"authenticated": true,
		"principal": "jourwon",
		"credentials": "N/A",
		"name": "jourwon"
	},
	"clientOnly": false,
	"oauth2Request": {
		"clientId": "admin",
		"scope": ["all"],
		"requestParameters": {
			"client_id": "admin"
		},
		"resourceIds": [],
		"authorities": [],
		"approved": true,
		"refresh": false,
		"redirectUri": null,
		"responseTypes": [],
		"extensions": {},
		"grantType": null,
		"refreshTokenRequest": null
	},
	"principal": "jourwon",
	"credentials": "",
	"name": "jourwon"
}

oauth2-client添加權限校驗

添加配置開啓基於方法的權限校驗:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(101)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}

在UserController中添加需要admin權限的接口:

@RestController
@RequestMapping("/user")
public class UserController {

    @PreAuthorize("hasAuthority('admin')")
    @GetMapping("/auth/admin")
    public Object adminAuth() {
        return "Has admin auth!";
    }

}

訪問需要admin權限的接口:http://localhost:9501/user/auth/admin

在這裏插入圖片描述

使用沒有admin權限的帳號,比如andy:123456獲取令牌後訪問該接口,會發現沒有權限訪問。

在這裏插入圖片描述

使用到的模塊

springcloud-learning
├── oauth2-jwt-server -- 使用jwt的oauth2認證測試服務
└── oauth2-client -- 單點登錄的oauth2客戶端服務

項目源碼地址

GitHub項目源碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章