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.