[学习笔记] SpringSecurity之OAuth2授权模式
# 学习 # · 2021-10-25
认识SpringSecurity-OAuth2
1、SpringSecurity OAuth2架构:
(1)用户访问Service,在没有Token时OAuth2RestTemplate会报错,且被Oauth2ClientContextFilter捕获到报错信息,并重定向到认证服务器(Authorization Server)。
(2)认证服务器通过授权端点(Authorization Endpoint)进行授权,并通过AuthorizationServerTokenServices生成授权码code并返回给客户端。
(3)客户端拿到授权码去认证服务器通过令牌端点(Token Endpoint)调用AuthorizationServerTokenServices生成令牌token并返回给客户端。
(4)客户端拿到token去资源服务器访问资源,通过Oauth2AuthenticationManager调用ResourceServerTokenServices进行校验,校验通过可以获取资源。
SpringSecurity-OAuth2授权模式
1、创建SpringBoot项目,并导入相关依赖。
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<!-- SpringSecurity OAuth2整合依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<!-- SpringBoot依赖 -->
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
2、创建SpringSecurity配置类:
/**
* @Package: com.duo.config
* @Description: SpringSecurity配置类
* @Author 多仔
*/
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/oauth/**", "/login/**", "/logout/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
}
/**
* @Author: 多仔
* @Description: 返回PasswordEncoder实例
* @return org.springframework.security.crypto.password.PasswordEncoder
**/
@Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
3、创建SpringSecurity自定义登录逻辑:
/**
* @Package: com.duo.service
* @Description: 自定义登录逻辑
* @Author 多仔
*/
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
String password = passwordEncoder.encode("123456");
return new User("admin", password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
4、创建资源服务器Controller:
/**
* @Package: com.duo.controller
* @Description: 用户中心控制器
* @Author 多仔
*/
@RestController
@RequestMapping(value = "/user")
public class UserController {
@GetMapping("/getUserInfo")
public Object getUserInfo(Authentication authentication) {
return authentication.getPrincipal();
}
}
5、授权服务器配置:
/**
* @Package: com.duo.config
* @Description: 授权服务器配置
* @Author 多仔
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 配置client_id
.withClient("client-demo")
// 配置client_secret
.secret(passwordEncoder.encode("abcd"))
// 配置redirect_uri,用于授权成功后跳转
.redirectUris("http://www.baidu.com")
// 配置申请的权限范围
.scopes("all")
// 配置grant-type,表示授权类型
.authorizedGrantTypes("authorization_code");
}
}
6、资源服务器配置:
/**
* @Package: com.duo.config
* @Description: 资源服务器配置
* @Author 多仔
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.requestMatchers()
//配置需要保护的资源路径
.antMatchers("/user/**");
}
}
7、启动项目,访问授权链接,登录正确的账号,获取授权码code:
http://localhost:8080/oauth/authorize?response_type=code&client_id=client-demo&redirect_uri=http://www.baidu.com&scope=all
8、根据授权码获取令牌token(使用PostMan模拟发送POST请求):
9、根据获取到的令牌token访问资源服务器请求获取资源:
在Redis中存储Token
1、在项目中引入Redis依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、编写Redis配置类:
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore(){
return new RedisTokenStore(redisConnectionFactory);
}
}
3、在授权服务器配置中指定令牌的存储策略为Redis:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
@Qualifier("redisTokenStore")
private TokenStore redisTokenStore;
@Autowired
private UserDetailServiceImpl userDetailService;
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(redisTokenStore)
.userDetailsService(userDetailService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// ...
}
}
4、使用PostMan请求Token:
5、在Redis客户端中查看结果:
如无特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/329/
如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/329/
评论