用Spring Cloud OAuth2保護微服務系統


一、簡介#

OAth2是一個標准的授權協議。

在認證與授權的過程中,主要包含以下3種角色。

  • 服務提供方 Authorization Server。
  • 資源持有者 Resource Server。
  • 客戶端 Client。

OAuth2的認證流程如圖所示,具體如下。

(1)用戶(資源持有者)打開客戶端 ,客戶端詢問用戶授權。

(2)用戶同意授權。

(3)客戶端向授權服務器申請授權。

(4)授權服務器對客戶端進行認證,也包括用戶信息的認證,認證成功后授權給予令牌。

(5)客戶端獲取令牌后,攜帶令牌向資源服務器請求資源。

(6)資源服務器確認令牌正確無誤,向客戶端釋放資源。

OAuth2 Provider 的角色被分為 Authorization Server(授權服務)和 Resource Service(資源服務),通常它們不在同一個服務中,可能一個 Authorization Service 對應多個 Resource Service。Spring OAuth2 需配合 Spring Security 一起使用,所有的請求由 Spring MVC 控制器處理,並經過一系列的Spring Security過濾器。

在Spring Security過濾器鏈中有以下兩個節點,這兩個節點是向 Authorization Service 獲取驗證和授權的。

  • 授權節點:默認為 /oauth/authorize。
  • 獲取Token節點:默認為 /oauth/token。

二、快速開始#

2.1 新建本地數據庫#

客戶端信息可以存儲在數據庫中,這樣就可以通過更改數據庫來實時更新客戶端信息的數據。Spring OAuth2 已經設計好了數據庫的表,且不可變。

Copy
/* Navicat MySQL Data Transfer Source Host : localhost Source Database : spring-cloud-auth Target Server Version : 50718 File Encoding : utf-8 */ SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for `clientdetails` -- ---------------------------- DROP TABLE IF EXISTS `clientdetails`; CREATE TABLE `clientdetails` ( `appId` varchar(128) NOT NULL, `resourceIds` varchar(256) DEFAULT NULL, `appSecret` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `grantTypes` varchar(256) DEFAULT NULL, `redirectUrl` varchar(256) DEFAULT NULL, `authorities` varchar(256) DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additionalInformation` varchar(4096) DEFAULT NULL, `autoApproveScopes` varchar(256) DEFAULT NULL, PRIMARY KEY (`appId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_access_token` -- ---------------------------- DROP TABLE IF EXISTS `oauth_access_token`; CREATE TABLE `oauth_access_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication_id` varchar(128) NOT NULL, `user_name` varchar(256) DEFAULT NULL, `client_id` varchar(256) DEFAULT NULL, `authentication` blob, `refresh_token` varchar(256) DEFAULT NULL, PRIMARY KEY (`authentication_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_approvals` -- ---------------------------- DROP TABLE IF EXISTS `oauth_approvals`; CREATE TABLE `oauth_approvals` ( `userId` varchar(256) DEFAULT NULL, `clientId` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `status` varchar(10) DEFAULT NULL, `expiresAt` datetime DEFAULT NULL, `lastModifiedAt` datetime DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_client_details` -- ---------------------------- DROP TABLE IF EXISTS `oauth_client_details`; CREATE TABLE `oauth_client_details` ( `client_id` varchar(256) NOT NULL, `resource_ids` varchar(256) DEFAULT NULL, `client_secret` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `authorized_grant_types` varchar(256) DEFAULT NULL, `web_server_redirect_uri` varchar(256) DEFAULT NULL, `authorities` varchar(256) DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additional_information` varchar(4096) DEFAULT NULL, `autoapprove` varchar(256) DEFAULT NULL, PRIMARY KEY (`client_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_client_token` -- ---------------------------- DROP TABLE IF EXISTS `oauth_client_token`; CREATE TABLE `oauth_client_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication_id` varchar(128) NOT NULL, `user_name` varchar(256) DEFAULT NULL, `client_id` varchar(256) DEFAULT NULL, PRIMARY KEY (`authentication_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_code` -- ---------------------------- DROP TABLE IF EXISTS `oauth_code`; CREATE TABLE `oauth_code` ( `code` varchar(256) DEFAULT NULL, `authentication` blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `oauth_refresh_token` -- ---------------------------- DROP TABLE IF EXISTS `oauth_refresh_token`; CREATE TABLE `oauth_refresh_token` ( `token_id` varchar(256) DEFAULT NULL, `token` blob, `authentication` blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `role` -- ---------------------------- DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `password` varchar(255) DEFAULT NULL, `username` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `UK_sb8bbouer5wak8vyiiy4pf2bx` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for `user_role` -- ---------------------------- DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `user_id` bigint(20) NOT NULL, `role_id` bigint(20) NOT NULL, KEY `FKa68196081fvovjhkek5m97n3y` (`role_id`), KEY `FK859n2jvi8ivhui0rl0esws6o` (`user_id`), CONSTRAINT `FK859n2jvi8ivhui0rl0esws6o` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`), CONSTRAINT `FKa68196081fvovjhkek5m97n3y` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; SET FOREIGN_KEY_CHECKS = 1;

2.2 新建Maven工程#

整個項目采用的是Maven多Module的形式,所以需要你新建一個空白的Maven工程,並在根目錄的pom.xml的配置Spring Boot的版本1.5.3.RELEASE,Spring Cloud的版本為Dalston.RELEASE,參考代碼

Copy

<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> </parent> <modules> <module>eureka-server</module> <module>service-auth</module> <module>service-hi</module> </modules> <groupId>cn.yueshutong</groupId> <artifactId>spring-cloud-autho2</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-cloud-autho2</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Dalston.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

2.3 編寫 Eureka Server#

新建模塊eureka-server,並添加Eureka依賴,此處要指定父工程

Copy

<?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>cn.yueshutong</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>eureka-server</name> <description>Demo project for Spring Boot</description> <parent> <groupId>cn.yueshutong</groupId> <artifactId>spring-cloud-autho2</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

在eureka-server工程的配置文件 application.yml 中配置 Eureka Server

Copy
server:  port: 8761 eureka:  instance:  hostname: localhost  client:  registerWithEureka: false  fetchRegistry: false  serviceUrl:  defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

最后,添加@EnableEurekaServer注解開啟Eureka Server的功能

Copy
@EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }

2.4 編寫 Uaa 授權服務#

1.新建模塊service-auth,並加入下列依賴,作為Uaa(授權服務)

Copy

<?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>cn.yueshutong</groupId> <artifactId>service-auth</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>service-auth</name> <description>Demo project for Spring Boot</description> <parent> <groupId>cn.yueshutong</groupId> <artifactId>spring-cloud-autho2</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

打開spring-cloud-starter-oauth2依賴可以看到,它已經整合了spring-cloud-starter-security、spring-security-oauth2 和 spring-security-jwt 這3個起步依賴。

2.配置 application.yml 做如下配置

Copy
spring:  application:  name: service-auth  datasource:  driver-class-name: com.mysql.jdbc.Driver  url: jdbc:mysql://localhost:3306/spring-cloud-auth?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8  username: root  password: 123456  jpa:  hibernate:  ddl-auto: update  show-sql: true server:  context-path: /uaa  port: 5000 security:  oauth2:  resource:  filter-order: 3 # basic: # enabled: false eureka:  client:  serviceUrl:  defaultZone: http://localhost:8761/eureka/

配置 security.oauth2.resource.filter-order 為3,在 Spring Boot1.5.x 版本之前,默認即可。

3.配置Spring Security

由於 auth-service 需要對外暴露檢查 Token 的API接口,所以 auth-service 也是一個資源服務,需要在工程中引入 Spring Security,並做相關配置,對 auth-service 資源進行保護。

Copy
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true)//注解開啟在方法上的保護功能 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserServiceDetail userServiceDetail; @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests().anyRequest().authenticated() .and() .csrf().disable(); // @formatter:on } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userServiceDetail).passwordEncoder(new BCryptPasswordEncoder()); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }

UserServiceDetail.java

Copy
@Service public class UserServiceDetail implements UserDetailsService { @Autowired private UserDao userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return userRepository.findByUsername(username); } }

User.java,需要實現 UserDetails 接口

Copy
@Entity public class User implements UserDetails, Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String username; @Column private String password; @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) private List<Role> authorities; public User() { } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } //setter getter @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }

Role.java,需要實現GrantedAuthority接口

Copy
@Entity public class Role implements GrantedAuthority { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; //setter getter @Override public String getAuthority() { return name; } @Override public String toString() { return name; } }

UserDao.java

Copy
public interface UserDao extends JpaRepository<User, Long> { User findByUsername(String username); }

4.配置Authorization Server

Copy
@SpringBootApplication @EnableResourceServer //開啟資源服務,因為程序需要對外暴露獲取token的API接口 @EnableEurekaClient //開啟Eureka Client public class ServiceAuthApplication { @Autowired @Qualifier("dataSource") private DataSource dataSource; public static void main(String[] args) { SpringApplication.run(ServiceAuthApplication.class, args); } @Configuration @EnableAuthorizationServer //開啟授權服務的功能 protected class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter { //將Token存儲在內存中 //private TokenStore tokenStore = new InMemoryTokenStore(); JdbcTokenStore tokenStore=new JdbcTokenStore(dataSource); @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Autowired private UserServiceDetail userServiceDetail; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //ClientDetailsServiceConfigurer配置了客戶端的一些基本信息 clients.inMemory() //將客戶端的信息存儲在內存中 .withClient("browser") //創建了一個client名為browser的客戶端 .authorizedGrantTypes("refresh_token", "password")//配置驗證類型 .scopes("ui")//配置客戶端域為“ui” .and() .withClient("service-hi") .secret("123456") .authorizedGrantTypes("client_credentials", "refresh_token","password") .scopes("server"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(tokenStore) //Token的存儲方式為內存 .authenticationManager(authenticationManager) //WebSecurity配置好的 .userDetailsService(userServiceDetail);//讀取用戶的驗證信息 } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { //配置獲取Token的策略 oauthServer .tokenKeyAccess("permitAll()") //對獲取Token的請求不再攔截 .checkTokenAccess("isAuthenticated()"); //驗證獲取Token的驗證信息 } } }

5.暴露Remote Token Service接口

本例采用 RemoteTokenService 這種方式對 Token 進行驗證。如果其他資源服務需要驗證 Token,則需要遠程調用授權服務暴露的驗證 Token 的API接口。

Copy
@RestController @RequestMapping("/users") public class UserController { //暴露Remote Token Services接口 //如果其它服務需要驗證Token,則需要遠程調用授權服務暴露的驗證Token的API接口 @RequestMapping(value = "/current", method = RequestMethod.GET) public Principal getUser(Principal principal) { return principal; } }

2.6 編寫service-hi資源服務#

1.新建模塊 service-hi ,這個工程作為資源服務。在pom文件引入如下依賴

Copy

<?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>cn.yueshutong</groupId> <artifactId>service-hi</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>service-hi</name> <description>Demo project for Spring Boot</description> <parent> <groupId>cn.yueshutong</groupId> <artifactId>spring-cloud-autho2</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 

2.配置application.yml文件

Copy
eureka:  client:  serviceUrl:  defaultZone: http://localhost:8761/eureka/ server:  port: 8762 spring:  application:  name: service-hi  datasource:  driver-class-name: com.mysql.jdbc.Driver  url: jdbc:mysql://localhost:3306/spring-cloud-auth?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8  username: root  password: 123456  jpa:  hibernate:  ddl-auto: update  show-sql: true security:  oauth2:  resource:  user-info-uri: http://localhost:5000/uaa/users/current #獲取當前Token的用戶信息  client:  clientId: service-hi  clientSecret: 123456  accessTokenUri: http://localhost:5000/uaa/oauth/token #獲取Token  grant-type: client_credentials,password  scope: server

3.配置 Resource Server

server-hi 工程作為 Resource Server(資源服務),需要配置 Resource Server的相關配置,配置代碼

Copy
@Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true)//開啟方法級別的保護 public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { //配置哪些請求需要驗證 http.authorizeRequests() .antMatchers("/user/registry").permitAll() .anyRequest().authenticated(); } }

4.配置OAuth2 Client

Copy
@EnableOAuth2Client //開啟OAuth2Client @EnableConfigurationProperties @Configuration public class OAuth2ClientConfig { @Bean @ConfigurationProperties(prefix = "security.oauth2.client")//獲取Bean的配置屬性 public ClientCredentialsResourceDetails clientCredentialsResourceDetails() { //配置受保護資源的信息 return new ClientCredentialsResourceDetails(); } /** * @EnableOAuth2Client. * 1.oauth2ClientContextFilter * 2.AccessTokenRequest */ @Bean public RequestInterceptor oauth2FeignRequestInterceptor(){ //配置一個過濾器,存儲當前請求和上下文 //在request域內創建 AccessTokenRequest 類型的Bean。 return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), clientCredentialsResourceDetails()); } @Bean public OAuth2RestTemplate clientCredentialsRestTemplate() { //向Uaa服務請求的 return new OAuth2RestTemplate(clientCredentialsResourceDetails()); } }

5.編寫用戶注冊接口

把service-auth的User.java、UserDao.java拷貝到service-hi工程。

Service層的UserServiceImpl類創建用戶,其中需要對密碼進行加密

Copy
@Service public class UserService { private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @Autowired private UserDao userDao; public User create(String username, String password) { User user=new User(); user.setUsername(username); String hash = encoder.encode(password); user.setPassword(hash); User u=userDao.save(user); return u; } }

編寫UserController.java

Copy
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/registry",method = RequestMethod.POST) public User createUser( @RequestParam("username") String username , @RequestParam("password") String password) { return userService.create(username,password); } }

編寫HiController類

Copy
@RestController public class HiController { Logger logger= LoggerFactory.getLogger(HiController.class); @Value("${server.port}") String port; //不需要任何權限,只要Header中的Token正確即可 @RequestMapping("/hi") public String home() { return "hi :"+",i am from port:" +port; } //需要ROLE_ADMIN權限 @PreAuthorize("hasAuthority('ROLE_ADMIN')") // @RequestMapping("/hello") public String hello (){ return "hello you!"; } //獲取當前“Token”用戶信息 @GetMapping("/getPrinciple") public OAuth2Authentication getPrinciple(OAuth2Authentication oAuth2Authentication, Principal principal, Authentication authentication){ logger.info(oAuth2Authentication.getUserAuthentication().getAuthorities().toString()); logger.info(oAuth2Authentication.toString()); logger.info("principal.toString()"+principal.toString()); logger.info("principal.getName()"+principal.getName()); logger.info("authentication:"+authentication.getAuthorities().toString()); return oAuth2Authentication; } }

6.啟動類

Copy
@SpringBootApplication @EnableEurekaClient public class ServiceHiApplication { public static void main(String[] args) { SpringApplication.run(ServiceHiApplication.class, args); } } 

下面依次啟動這3個工程。

2.7 PostMan驗證#

1.注冊用戶,返回注冊成功信息

2.獲取Token

3.訪問/hi,不需要權限,只要Token正確即可

4.訪問/hello,需要ROLE_ADMIN權限

訪問不成功,在數據庫role表添加權限信息ROLE_ADMIN,然后在user_role表關聯下,再次訪問。

需要注意的是Token在Header的位置,以及前戳。

總結#

本案列架構有改進之處。例如在資源服務器加一個登錄接口,該接口不受Spring Security 保護。登錄成功后,service-hi 遠程調用 auth-service 獲取 Token 返回給瀏覽器,瀏覽器以后所有的請求都需要攜帶該 Token。
這個架構的缺陷就是每次請求都需要資源服務內部遠程調用 auth-service 服務來驗證 Token 的正確性,以及該Token對應的用戶所具有的權限,額外多了一次內部請求。如果在高並發的情況下,auth-service 需要集群部署,並且需要做緩存處理。所以最佳方案還是使用 Spring Security OAuth2 以JWT的形式來保護Spring Cloud構建的微服務系統。


免責聲明!

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



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