Oauth2授权服务搭建

179 阅读2分钟

Oauth2授权服务搭建

  • 授权码模式 (Authorization Code) --先交互一次code,再用code获取token
  • 简化模式(Implicit)--直接用client_id获取token
  • 密码模式(password)--账号密码获取token
  • 客户端模式(Client Credentials) --通过client_idclient_secret获取token

SpingOauth2集成了这四种方式,下面是集成步骤。

1.数据库

使用oauth2,需要导入官方给的6张表,来存储client信息和token信息

image.png

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

集成管理useroauth_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

image.png

password

image.png

implcit

image.png

authorization_code

image.png

image.png