下面是关于“Spring Security如何优雅的增加OAuth2协议授权模式”的完整攻略。
什么是OAuth2协议授权模式
OAuth2是一个开放标准协议,用于授权第三方应用访问用户在某个服务提供商上存储的资源。OAuth2协议有四种授权模式,分别是:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
其中,授权码模式和简化模式较为常用。
Spring Security如何优雅的增加OAuth2协议授权模式
Spring Security为我们提供了完善的支持,可以轻松的集成OAuth2。
首先,需要在pom.xml中添加spring-security-oauth2依赖包。
下面,我们以Spring Boot为例,详细介绍如何增加OAuth2协议授权模式。
配置文件
在配置文件中添加相关配置:
spring:
security:
oauth2:
client:
registration:
client-id:
client-secret:
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name:client_name
client-id-2:
client-secret:
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name:client_name_2
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
token-uri: https://github.com/login/oauth/access_token
user-info-uri: https://api.github.com/user
user-name-attribute: id
其中,client注册信息包括client-id、client-secret、authorization-grant-type、redirect-uri和client-name。provider信息包括authorization-uri、token-uri、user-info-uri和user-name-attribute。
配置类
创建一个配置类,添加@EnableWebSecurity注解,并继承WebSecurityConfigurerAdapter。
然后,覆盖configure(HttpSecurity http)方法,配置HttpSecurity。
接着,创建一个OAuth2客户端,用于向OAuth2服务发送请求。
最后,在应用启动时添加@Configuration注解的类。
示例如下:
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/","/error","/webjars/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(
clientRegistration()
);
}
private ClientRegistration clientRegistration() {
return ClientRegistration
.withRegistrationId("github")
.clientId("clientId")
.clientSecret("clientSecret")
.clientName("clientName")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/github")
.scopes("read:user")
.authorizationUri("https://github.com/login/oauth/authorize")
.tokenUri("https://github.com/login/oauth/access_token")
.userInfoUri("https://api.github.com/user")
.userNameAttributeName("id")
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
.build();
}
@Bean
public OAuth2AuthorizedClientService authorizedClientService(
ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext,
OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
@Bean
public OAuth2ClientContext oauth2ClientContext() {
return new DefaultOAuth2ClientContext();
}
@Configuration
protected static class OAuth2RestOperationsConfiguration {
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Autowired
private OAuth2ProtectedResourceDetails details;
@Bean
public OAuth2RestOperations restTemplate() {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
}
}
示例
下面,我们通过两个示例进一步理解OAuth2协议授权模式。
- 授权码模式(authorization code)
首先,用户打开客户端,客户端引导用户打开授权服务器(Authorization Server)的认证界面,用户输入自己的用户名和密码,授权服务器认证成功后,会生成一组授权码Authorization Code返回给客户端。
然后,客户端携带授权码Authorization Code向认证服务器用HTTPS协议发送获取令牌Token的请求,认证服务器验证客户端身份和授权码的合法性后,会向客户端返回令牌Token,并在返回的数据中标示出此Token的有效期。
示例代码如下:
1)配置文件:
spring:
security:
oauth2:
client:
registration:
github:
client-id: 1234567890
client-secret: XXXXXXXX
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/github
scope:
- read:user
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
user-info-uri: https://api.github.com/user
token-uri: https://github.com/login/oauth/access_token
user-name-attribute: login
2)授权码请求:
@GetMapping("/authorize")
public void authorize(@RequestParam("code") String code, @RequestParam("state") String state, HttpServletResponse response)
throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
OAuth2AccessToken accessToken;
try {
accessToken = restTemplate.getAccessToken();
} catch (Exception ex) {
// 不同的错误可能具有不同的HTTP状态代码,请根据需要进行判断。
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
return;
}
Map<String, String> tokens = new HashMap<>();
tokens.put("accessToken", accessToken.getValue());
tokens.put("refreshToken", accessToken.getRefreshToken().getValue());
tokens.put("expiresIn", String.valueOf(accessToken.getExpiresIn()));
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
objectMapper.writeValue(response.getWriter(), tokens);
}
- 简化模式(implicit)
简化模式与授权码模式类似,不同之处在于,授权服务器通过URI返回Access Token。
客户端通过向授权服务器的认证界面发起请求,授权服务器验证身份后,直接返回AccessToken。
即客户端获得Access Token,但没有Refresh Token。AccessToken直接作为参数暴露在URL中。
示例代码如下:
1)配置文件:
spring:
security:
oauth2:
client:
registration:
client-id:
client-secret:
authorization-grant-type: implicit
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name:client_name
client-id-2:
client-secret:
authorization-grant-type: implicit
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
client-name:client_name_2
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
user-info-uri: https://api.github.com/user
token-uri: https://github.com/login/oauth/access_token
user-name-attribute: login
2)授权码请求:
@GetMapping("/callback")
public void callback(@RequestParam String access_token) {
logger.info("access_token=" + access_token);
}
以上就是关于“Spring Security如何优雅的增加OAuth2协议授权模式”的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security如何优雅的增加OAuth2协议授权模式 - Python技术站