SpringBoot实现标准的OAuth服务提供商
⒈添加pom依赖
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-security</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-web</artifactId> 8 </dependency> 9 <dependency> 10 <groupId>org.springframework.security.oauth</groupId> 11 <artifactId>spring-security-oauth2</artifactId> 12 <version>2.3.5.RELEASE</version> 13 </dependency> 14 <dependency> 15 <groupId>org.springframework.boot</groupId> 16 <artifactId>spring-boot-starter-test</artifactId> 17 <scope>test</scope> 18 </dependency> 19 <dependency> 20 <groupId>org.springframework.security</groupId> 21 <artifactId>spring-security-test</artifactId> 22 <scope>test</scope> 23 </dependency>
⒉配置SpringSecurity
1 package cn.coreqi.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 5 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 import org.springframework.security.config.annotation.web.builders.WebSecurity; 7 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 import org.springframework.security.crypto.password.NoOpPasswordEncoder; 10 import org.springframework.security.crypto.password.PasswordEncoder; 11 12 @EnableWebSecurity 13 public class CoreqiWebSecurityConfig extends WebSecurityConfigurerAdapter { 14 @Override 15 protected void configure(HttpSecurity http) throws Exception { 16 http.httpBasic() 17 .and() 18 .authorizeRequests() 19 .antMatchers("/oauth/token").permitAll() 20 .anyRequest().authenticated() //任何请求都需要身份认证 21 .and().csrf().disable(); //禁用CSRF 22 } 23 24 25 26 @Override 27 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 28 auth.inMemoryAuthentication() 29 .withUser("fanqi").password("admin").roles("admin"); 30 } 31 32 @Bean 33 public PasswordEncoder passwordEncoder() 34 { 35 return NoOpPasswordEncoder.getInstance(); 36 } 37 }
⒊配置OAuth
1 package cn.coreqi.config; 2 3 import org.springframework.context.annotation.Configuration; 4 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 5 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer; 6 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 7 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 8 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 9 10 @Configuration 11 @EnableAuthorizationServer //开启认证服务器 12 public class CoreqiAuthorizationServerConfig implements AuthorizationServerConfigurer { 13 14 @Override 15 public void configure(AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer) throws Exception { 16 17 } 18 19 @Override 20 public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception { 21 clientDetailsServiceConfigurer.inMemory() 22 .withClient("coreqi") 23 .secret("coreqiSecret") 24 .redirectUris("https://www.baidu.com") 25 .scopes("ALL") 26 .authorities("COREQI_READ") 27 .authorizedGrantTypes("authorization_code"); 28 } 29 30 @Override 31 public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception { 32 33 } 34 }
⒋测试【如果颁发给用户的令牌没有过期,那么Spring OAuth不会颁发新的令牌,而是将上次的令牌重新返回,不同的是过期时间减少了】
1.访问http://localhost:8080/登录
为什么要登录?因为这个地址是我们提供给第三方应用,由第三方应用来引导用户进行授权的,作为服务提供商,我们需要知道,1.是那个应用在请求授权(通过client_id),2.第三方应用在请求我们哪个用户的授权(通过此时登录的用户名密码判断是我们系统中的哪个用户),3.需要我们给第三方应用该用户的哪些权限(通过scope参数,scope参数是由我们自己定义的)。
参数介绍:
response_type:必填,值必须为code
client_id:必填,客户端id
redirect_uri:可选,授权码模式下可用
scope:必须要有,要么在服务器端配置,要么在请求参数中配置。
state:推荐
3.跳转到 redirect_uri 【https://www.baidu.com/?code=5HF6y7】拿到授权码
4.
ⅰ授权码模式:
对http://localhost:8080/oauth/token发送post请求,请求头添加Authorization,username为client_id,password为secret。BODY中添加以下参数:
grant_type:必填,值为authorization_code
code:授权码
redirect_uri:可选,授权码模式下可用
client_id:必填,客户端id
scope:和上一步请求传一样的值
ⅱ密码模式:
密码模式实际上是用户把自己在服务提供商的用户名密码告诉了第三方应用,第三方应用拿着用户名密码来服务提供商这里获得授权。这种情况下服务提供商是没法判断这个用户名密码是不是用户真正给你的(万一是你偷的呢)。
对http://localhost:8080/oauth/token发送post请求,请求头添加Authorization,username为client_id,password为secret。BODY中添加以下参数:
grant_type:必填,值为password
username:服务提供商系统中的用户
password:服务提供商系统中用户的密码
scope:和上一步请求传一样的值
密码模式需要对Security和OAuth做一些配置
1 package cn.coreqi.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.security.authentication.AuthenticationManager; 5 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 import org.springframework.security.crypto.password.NoOpPasswordEncoder; 10 import org.springframework.security.crypto.password.PasswordEncoder; 11 12 @EnableWebSecurity 13 public class CoreqiWebSecurityConfig extends WebSecurityConfigurerAdapter { 14 15 @Override 16 @Bean 17 public AuthenticationManager authenticationManagerBean() throws Exception { 18 return super.authenticationManagerBean(); 19 } 20 21 @Override 22 protected void configure(HttpSecurity http) throws Exception { 23 http.httpBasic() 24 .and() 25 .authorizeRequests() 26 .antMatchers("/oauth/token").permitAll() 27 .anyRequest().authenticated() //任何请求都需要身份认证 28 .and().csrf().disable(); //禁用CSRF 29 } 30 31 @Override 32 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 33 auth.inMemoryAuthentication() 34 .withUser("fanqi").password("admin").roles("admin"); 35 } 36 37 @Bean 38 public PasswordEncoder passwordEncoder() 39 { 40 return NoOpPasswordEncoder.getInstance(); 41 } 42 }
1 package cn.coreqi.config; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.security.authentication.AuthenticationManager; 7 import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 8 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 9 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 10 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 11 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 12 13 @Configuration 14 @EnableAuthorizationServer //开启认证服务器 15 public class CoreqiAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 16 17 @Autowired 18 @Qualifier("authenticationManagerBean") 19 private AuthenticationManager authenticationManager; 20 21 @Autowired 22 private AuthenticationConfiguration authenticationConfiguration; 23 24 /** 25 * password模式需要提供一个AuthenticationManager到AuthorizationServerEndpointsConfigurer 26 * @param authorizationServerEndpointsConfigurer 27 * @throws Exception 28 */ 29 @Override 30 public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception { 31 authorizationServerEndpointsConfigurer.authenticationManager(authenticationConfiguration.getAuthenticationManager()); 32 } 33 34 @Override 35 public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception { 36 clientDetailsServiceConfigurer.inMemory() 37 .withClient("coreqi") 38 .secret("coreqiSecret") 39 .redirectUris("https://www.baidu.com") 40 .scopes("ALL") 41 .authorities("COREQI_READ") 42 .authorizedGrantTypes("authorization_code","password"); 43 } 44 45 }
ⅲ刷新令牌