Spring Security OAuth 项目已经被弃用了,停止维护...
在 2020/04/15 这天,Spring 团队又宣布新起《Spring Authorization Server》项目,以继续提供对 Spring 授权服务器的支持...
1、OAuth 2.0 中的提供者角色实际上分为授权服务和资源服务,虽然它们有时驻留在同一个应用程序中,但使用 Spring Security OAuth,您可以选择将它们拆分为两个应用程序,也可以让多个资源服务共享授权服务。
2、OAuth四种模式
● 授权码模式(authorization code)
● 简化模式(implicit)
● 密码模式(resource owner password credentials)
● 客户端模式(client credentials)
3、UAA核心三个配置【AuthorizationServerConfigurerAdapter】
@EnableAuthorizationServer注解被用来配置授权服务器
ClientDetailServiceConfigurerr:配置客户端详情服务(ClientDetailsService)
AuthorizationServerEndpointsConfigurer:配置令牌端点的安全约束
AuthorizationServerSecurityConfigurer:配置令牌(token)的访问短点和令牌服务(tokenService)
4、令牌请求由 Spring MVC 控制器端点处理,对受保护资源的访问由标准 Spring Security 请求过滤器处理。为了实现 OAuth 2.0 授权服务器,Spring Security 过滤器链中需要以下端点:
AuthorizationEndpoint用于服务授权请求。默认网址:http://localhost:8080/oauth/authorize
TokenEndpoint用于服务访问令牌的请求。默认网址:http://localhost:8080/oauth/token
5、客户端模式 client_credentials
客户端向授权服务器发送自己的身份信息,请求令牌access_token
http://localhost:8080/oauth/token?client_id=client&client_secret=secret&grant_type=client_credentials
Postman 请求
6、密码模式
http://localhost:8080/oauth/token?client_id=client&client_secret=secret&grant_type=password&username=admin&password=123456
*
7、简化模式
1、http://localhost:8080/login 输入账号密码
2、再次输入如下地址,获取token
http://localhost:8080/oauth/authorize?response_type=token&client_id=client&redirect_uri=http://example.com&scope=write
地址栏重定向如下
http://example.com/#access_token=2820363f-2e2f-4485-8892-64683895675e&token_type=bearer&expires_in=3512
*
8、授权码模式
1、http://localhost:8080/login 输入账号密码
2、再次输入如下地址,获取code
http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://example.com&scope=write
地址栏重定向如下
http://example.com/?code=n9WlYp
3、http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client_id_1&client_secret=123456&redirect_uri=http://example.com&code=n9WlYp
9、pom.xml 添加依赖
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.11.RELEASE</version>
</dependency>
<!--引入security对oauth2的支持-->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
10、OAuth2AuthorizationServer.java 授权服务配置类
ClientDetailsServiceConfigurer:配置客户端详情服务(ClientDetailsService)
AuthorizationServerSecurityConfigurer:配置令牌(token)的访问短点和令牌服务(tokenService)
AuthorizationServerEndpointsConfigurer:配置令牌端点的安全约束
package com.example.demosecurity0218.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
// 1. 配置客户端
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 添加一个client配置,指定其client_id
.withClient("client_1")
// 指定客户端的密码/安全码
.secret(new BCryptPasswordEncoder().encode("secret"))
// 指定客户端所能访问资源id清单,此处的资源id是需要在具体的资源服务器上也配置一样
.resourceIds("salary")
.authorizedGrantTypes("authorization_code", "password", "implicit","client_credentials","refresh_token")
// 客户端的权限范围,此处配置为all全部即可
.scopes("all")
// 跳转到授权页面
.autoApprove(false)
// 回调地址
.redirectUris("http://www.baidu.com");
}
// 2. 配置令牌访问端点
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// 指定认证管理器,随后注入一个到当前类使用即可
.authenticationManager(authenticationManager)
// 密码模式用户信息管理
.userDetailsService(userDetailsService)
// 授权码服务
.authorizationCodeServices(authorizationCodeServices)
.authorizationCodeServices(new InMemoryAuthorizationCodeServices())
// token服务的一个描述,可以认为是token生成细节的描述,比如有效时间多少等
.tokenServices(tokenServices())
// 指定token的存储方法
.tokenStore(tokenStore)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
// 3. 配置令牌端点的安全策略
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
// 开启端口/oauth/token_key的访问权限(允许)
.tokenKeyAccess("permitAll()")
// 开启端口/oauth/check_token的访问权限(允许)
.checkTokenAccess("permitAll()")
// 允许客户端表单认证,申请令牌
.allowFormAuthenticationForClients();
}
/**
* 该方法用户获取一个token服务对象(该对象描述了token有效期等信息)
*/
public AuthorizationServerTokenServices tokenServices() {
// 使用默认实现
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(clientDetailsService);
// 开启令牌自动刷新
services.setSupportRefreshToken(true);
// 令牌存储策略-内存
//services.setTokenStore(tokenStore());
services.setTokenStore(tokenStore);
// 使用 JWT令牌
services.setTokenEnhancer(accessTokenConverter);
// 设置令牌有效时间(一般设置为2个小时),当前设置5秒钟
services.setAccessTokenValiditySeconds(300);
// 设置刷新令牌的有效时间 3天
services.setRefreshTokenValiditySeconds(259200);
return services;
}
}
*
11、SecurityConfig.java
package com.example.demosecurity0218.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
@Configuration
@EnableWebSecurity
//@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
//@Order(-1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String SIGN_KEY = "UAA";
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password(passwordEncoder().encode("123")).roles("ADMIN")
.and()
.withUser("user").password(passwordEncoder().encode("123")).roles("USER")
.and()
.withUser("king").password(passwordEncoder().encode("123")).roles("USER", "ADMIN");;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
// 从父类加载认证管理器
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Bean
public AuthorizationCodeServices authorizationCodeServices(){
return new InMemoryAuthorizationCodeServices();
}
@Bean
public UserDetailsService userDetailsService(){
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return null;
}
};
}
@Bean
public JwtAccessTokenConverter accessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGN_KEY);
return converter;
}
}
postman获取token:
http://localhost:8080/oauth/token
检查token
http://localhost:8080/oauth/check_token
*
*
*