Oauth2授权服务搭建
- 授权码模式 (
Authorization Code) --先交互一次code,再用code获取token - 简化模式(
Implicit)--直接用client_id获取token - 密码模式(
password)--账号密码获取token - 客户端模式(
Client Credentials) --通过client_id和client_secret获取token
SpingOauth2集成了这四种方式,下面是集成步骤。
1.数据库
使用oauth2,需要导入官方给的6张表,来存储client信息和token信息
2.依赖引入
pom.xml依赖如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- nacos服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
3.application.yml
server:
port: 9091
Spring:
application:
name: oauth2-service
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 198.10.1.58:9001
config:
server-addr: 198.10.1.58:9001
file-extension: yaml
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/oauth?characterEncoding=utf-8&serverTimezone=GMT%2B8&userSSL=false
password: 1111
username: root
4.配置
UserService
因为用到了账号密码模式,所以要写其UserService以供spring调用
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(!StringUtils.hasLength(username)){
throw new RuntimeException("用户名不能为空");
}
User user = userRepository.findByUsername(username);
if(user != null){
return new org.springframework.security.core.userdetails.User(
username,user.getPassword(), AuthorityUtils.createAuthorityList(user.getPassword())
);
}
throw new UsernameNotFoundException("user not found!");
}
}
Oauth2Config
集成管理user、oauth_client_details表,通过datasource链接注入,authenticationManager权限管理注入
@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private UserService userService;//user表
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Primary
@Bean
public DefaultTokenServices defaultTokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setAccessTokenValiditySeconds(30 * 24 * 3600);
return tokenServices;
}
//client_id 、client_secret,oauth_client_details表中的信息存储
@Bean
public ClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
/**
* 访问安全配置
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()//允许客户端表单提交
.checkTokenAccess("permitAll()");
}
/**
* oauth2客户端配置
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
/**
* 配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenServices(defaultTokenServices());
endpoints.userDetailsService(userService);
endpoints.authenticationManager(authenticationManager);
}
}
WebSecurityConfig
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//供O2config使用
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return passwordEncoder().encode(rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return passwordEncoder().matches(rawPassword,encodedPassword);
}
});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and()
.httpBasic()
.and().cors()
.and().csrf().disable();//csrf不支持post
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/swagger-*")//不需要验证的接口
.antMatchers("/login-*");
}
测试
client credentials
password
implcit
authorization_code