spring-security-oauth2 密码模式
OAuth 2
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.3.RELEASE</version> </dependency> <!--redis依赖配置--> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
由于Spring Boot中的OAuth协议是在Spring Security的基础上完成的,因此首先要添加Spring Security依赖,
要用到OAuth 2,因此添加OAuth 2相关依赖,
令牌可以存储在Redis缓存服务器上,同时Redis具有过期等功能,很适合令牌的存储,因此也加入Redis依赖。
配置Redis服务器的连接信息:
spring:
redis:
host: localhost # Redis服务器地址
database: 0 # Redis数据库索引(默认为0)
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码(默认为空)
jedis:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
timeout: 3000ms # 连接超时时间(毫秒)
配置授权服务器:
授权服务器和资源服务器可以是同一台服务器,也可以是不同服务器,本案例中假设是同一台服务器,通过不同的配置分别开启授权服务器和资源服务器,首先是授权服务器:
/**
* 自定义类继承自AuthorizationServerConfigurerAdapter,完成对授权服务器的配置
*/
@Configuration
@EnableAuthorizationServer // 通过@EnableAuthorizationServer注解开启授权服务器
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager; // 该对象将用来支持password模式
@Autowired
RedisConnectionFactory redisConnectionFactory; // 该对象将用来完成Redis缓存,将令牌信息存储到Redis缓存中。
@Autowired
UserDetailsService userDetailsService; // 该对象将为刷新token提供支持
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("password")
/*
* 表示OAuth 2中的授权模式为“password”和“refresh_token”两种
* 在标准的OAuth 2协议中,授权模式并不包括“refresh_token”,但是在Spring Security的实现中将其归为一种,
* 因此如果要实现access_token的刷新,就需要添加这样一种授权模式
*/
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(1800) // 配置了access_token的过期时间
.resourceIds("rid") // resourceIds配置了资源id
.scopes("all")
.secret("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq");//secret方法配置了加密后的密码,明文是123
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
/*
* 配置了令牌的存储,AuthenticationManager和UserDetailsService主要用于支持password模式以及令牌的刷新。
*/
endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.allowFormAuthenticationForClients();// 表示支持client_id和client_secret做登录认证
}
}
配置资源服务器:
@Configuration
@EnableResourceServer // @EnableResourceServer注解开启资源服务器配置
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
// 配置资源id,这里的资源id和授权服务器中的资源id一致,然后设置这些资源仅基于令牌认证。
resources.resourceId("rid").stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated();
}
}
配置Security:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 这里两个Bean将注入授权服务器配置类中使用
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
protected UserDetailsService userDetailsService() {
return super.userDetailsService();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
.roles("admin")
.and()
.withUser("sang")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
.roles("user");
}
/**
* 在Spring Security配置和资源服务器配置中,一共涉及两个HttpSecurity,
* 其中Spring Security中的配置优先级高于资源服务器中的配置,即请求地址先经过Spring Security的HttpSecurity,再经过资源服务器的HttpSecurity。
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth/**").authorizeRequests()
.antMatchers("/oauth/**").permitAll()//这里的HttpSecurity配置主要是配置“/oauth/**”模式的URL,这一类的请求直接放行
.and().csrf().disable();
}
}
测试验证:
启动Redis服务器,再启动Spring Boot项目,首先发送一个POST请求获取token,请求地址如下
POST http://127.0.0.1:8081/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123
当access_token过期后,使用refresh_token重新获取新的access_token(前提是refresh_token未过期),请求地址如下
POST http://127.0.0.1:8081/oauth/token?grant_type=refresh_token&refresh_token=6b80de74-e264-4ca5-b 9cc-20e8a6fa486d&client_id=password&client_secret=123
接下来访问资源,携带上access_token参数即可
GET http://127.0.0.1:8081/user/hello?access_token=4c0ab1bd-5e01-4420-aa79-a4acf79fe7d2
文章来源: Spring Boot+Vue全栈开发实战 - 10.4 OAuth 2

浙公网安备 33010602011771号