Code address: github.com/toyranger/l…

User authentication and authorization

OAuth is a protocol that does not allow third parties to access user account information. That is, third parties can apply for authorization of user resources without using the user name and password. Spring Security, Apache Shiro are all implementations

1. Access and refresh of Spring Security oAuth2 tokens

Access Token

The Refresh Token is used to Refresh the Access Token. The authentication server provides a Refresh interface

http://www.somesite.com/refresh?refresh_token=&client_id=
Copy the code

2. Spring Security oAuth2 client authorization mode

  • Implicit simplification model
  • Authorization Indicates the authorization code mode
  • Resource Owner Password Credentials Password mode
  • Client Credentials Client mode

This may be asked in the interview, check the information, understand.

3. Obtain authorization code and Access_token (in-memory mode, for testing)

## pom.xml<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId>  </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>Copy the code
/ / @ the authentication server Configuration @ EnableWebSecurity @ EnableGlobalMethodSecurity (prePostEnabled =true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Bean
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("123456"))
        .roles("USER").and().withUser("admin").password(passwordEncoder().encode("admin"))
        .roles("ADMIN"); }}Copy the code
/ / authorization server @ Configuration @ EnableAuthorizationServer public class AuthorizationConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired private BCryptPasswordEncoder passwordEncoder; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient("client").secret(passwordEncoder.encode("secret"))
        .authorizedGrantTypes("authorization_code").scopes("app")
        .redirectUris("https://www.baidu.com"); }}Copy the code

4. Obtain the authorization code and token

http://localhost:8080/oauth/authorize?client_id=client&response_type=code request will be redirected to the specified address, the address is finally authorization codeCopy the code
http://client:secret@localhost:8080/oauth/token
Copy the code

This access_token is used to request the resource server

5. Obtain the authorization code and access_token(JDBC mode)

Initialize the database using the official PROVIDED SQL github.com/spring-proj… Fill in the client/secret information in the table

5.1 application. Yml

Spring: application: name: oauth2 - resources datasource: jdbcUrl: JDBC: mysql: / / 192.168.0.106:3306 / oauth2? serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
    driverClassName: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      auto-commit: true
      minimum-idle: 2
      idle-timeout: 60000
      connection-timeout: 30000
      max-lifetime: 1800000
      pool-name: DatebookHikariCP
      maximum-pool-size: 5
Copy the code

5.2 Authorization Server information is obtained from JDBC

@Configuration @EnableAuthorizationServer public class AuthorizationConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired private BCryptPasswordEncoder passwordEncoder; @bean@primary @configurationProperties (prefix =); // The default is HikariDataSource"spring.datasource")
  public DataSource dataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  public TokenStore tokenStore() {
    return new JdbcTokenStore(dataSource());
  }

  @Bean
  public ClientDetailsService jdbcClientDetailsService() {
    returnnew JdbcClientDetailsService(dataSource()); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(jdbcClientDetailsService()); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore()); }}Copy the code

After the interface for obtaining the authorization code and token succeeds in obtaining the token, you can see that data has been generated in the database

6. RBAC authorization model

Role-Based Access Control

SQL in the code base, you can use Mybatis -plus automatically generate template code

6.1 User Authentication – Queries users by user name and permissions by user ID

WebSecurityConfiguration Uses userDetailsService for authentication

 @Bean
  @Override
  public UserDetailsService userDetailsService() {
    return new UserDetailsServiceImpl();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth.userDetailsService(userDetailsService());
  }
Copy the code

UserDetailsService Implements the class to access the database and query users and permissions

@Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserService userService;  @Autowired private PermissionService permissionService; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { User userByUsername = userService.getUserByUsername(s); List<GrantedAuthority> grantedAuthorities = Lists.newArrayList();if(null ! = userByUsername) { List<Permission> permissions = permissionService.selectByUserId(userByUsername.getId()); permissions.forEach(permission -> { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getEnname()); grantedAuthorities.add(grantedAuthority); });return new org.springframework.security.core.userdetails.User(userByUsername.getUsername(),
          userByUsername.getPassword(), grantedAuthorities);
    }

    return null;
  }
Copy the code
<select id="selectByUserId" resultMap="BaseResultMap">
    select p.* from tb_user as u
    left join tb_user_role as ur on u.id = ur.user_id
    left join tb_role as r on r.id = ur.role_id
    left join tb_role_permission as rp on r.id = rp.role_id
    left join tb_permission as p on p.id = rp.permission_id
    where u.id = #{userId};
  </select>
Copy the code

Then — get the authorization code — get the token, same process as before

7. Create a resource server

To test the permissions of different users’ tokens, use the TB_permission table

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class ResourcesServerConfiguration extends ResourceServerConfigurerAdapter {

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http.exceptionHandling().and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/").hasAnyAuthority("System")
        .antMatchers("/content").hasAuthority("SystemContent"); }}Copy the code

Associate the resource server with the authentication and authorization server by configuring:

security:
  oauth2:
    client:
      client-id: client
      client-secret: secret
      access-token-uri: http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
    resource:
      token-info-uri: http://localhost:8080/oauth/check_token

Copy the code
@restController Public Class HelloController {/*** * Test"/"Required permissions * @return
   */
  @GetMapping("/")
  public String hello() {

    return "hello, oauth2"; }}Copy the code

According to the resource server configuration, / requires System permissions, and corresponds to the database configuration, so it should be accessible now.

Get authorization code — Get token — Access /

If I change the permission of/to System > System111, then “user” will not have permission again, as shown in the following figure:

My feelings 0.

When I first learned Spring Security, authentication and authorization server and resource server are configured in a configuration, which is not easy to understand. This oAuth2 is much better and clear.