Basic use of spring Security + oauth2 + JWT
MyDistance 2021-06-04 09:02:08

Spring Security + OAuth2 + JWT Basic use

I learned from the front Spring Security introduction , Now match oauth2 + JWT To test .

1、 What is? OAuth2

OAuth It's about empowerment (authorization) Open network standards , So that third party applications can use the token in Time limit Limit the scope Access specified resources . It's widely used all over the world , The current version is 2.0 edition .

1.1、 About OAuth2 Several important concepts of :

  • resource owner: Users who have access to resources
  • user-agent: Generally speaking, it's a browser
  • client: Third-party applications
  • Authorization server: Authentication server , Used for user authentication and issuing token
  • Resource server: Resource server , The server that owns the accessed resources , Need to pass through token To determine if you have access to

1.2、 Handshake process

When the concept is clear , You can see OAuth2 Protocol handshake flow of , Excerpt from RFC6749

image-20210519120117924

(A) After the user opens the client , Client requires authorization from user .

(B) User agrees to authorize client .

(C) The client uses the authorization obtained in the previous step , Request token from authentication server .

(D) After the authentication server authenticates the client , Confirm no mistake , Agree to issue token .

(E) Client use token , Request resources from resource server .

(F) Resource server confirms that the token is correct , Agree to open resources to clients

1.3、 Authorization mode

oauth2 Depending on the use scenario , Divided into 4 Patterns

  • Authorization code mode (authorization code)
  • Simplified mode (implicit)
  • Password mode (resource owner password credentials)
  • Client mode (client credentials)

Authorization code mode uses callback address , It's the most complicated way , Usually, there are microblogs in websites ,qq Third party login , Will take this form . Simplified patterns are not commonly used .

2、 To configure

Use oauth2 Protect your app , It can be divided into three simple steps

  • Configure resource servers
  • Configure the license server
  • To configure spring security

2.1、maven Depend on the configuration

I'll introduce spring-cloud oauth2, More convenient for future expansion .

<!--spring boot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!--spring cloud oauth2-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!--spring cloud security-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<!--JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<!--spring cloud-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

2.2、 Configure the license server

Here you need to configure the access client , And configure the authorization type and access_token turn jwtToken.

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailServiceImpl userDetailService;
@Autowired
@Qualifier("jwtTokenStore")
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private JwtTokenEnhancer jwtTokenEnhancer;
/**
* Configure authorization types
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// Set up Jwt Content enhancement
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> list = new ArrayList<>();
list.add(jwtTokenEnhancer);
list.add(jwtAccessTokenConverter);
tokenEnhancerChain.setTokenEnhancers(list);
endpoints
// Password mode must be configured
.authenticationManager(authenticationManager)
// Password mode must be configured
.userDetailsService(userDetailService)
//accessToken turn JwtToken
.tokenStore(tokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
//jwt Content enhancement
.tokenEnhancer(tokenEnhancerChain);
}
/**
* Configure client details
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.
// Based on memory configuration
inMemory()
// client ID
.withClient("client")
// secret key
.secret(bCryptPasswordEncoder.encode("112233"))
// Redirect address
.redirectUris("http://www.baidu.com")
// Scope of Authorization
.scopes("all")
//accessToken Valid time
.accessTokenValiditySeconds(60)
//refreshToken Valid time
.refreshTokenValiditySeconds(3600)
/**
* Type of Authorization
* authorization_code: Authorization code mode
* password: Password mode
* refresh_token: Refresh token
*/
.authorizedGrantTypes("authorization_code", "password", "refresh_token");
}
}

2.3、 Configure resource servers

Inherit ResourceServerConfigurerAdapter And add @EnableResourceServer annotation

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// Intercept all requests
.anyRequest()
.authenticated()
.and()
//spring secuity Provides requestMatchers Interface , Equivalent to http.authorizeRequests().anyRequest().access("permitAll");
// Providing resources , visit /user Authority authentication is required
.requestMatchers()
.antMatchers("/user/**");
}
}

2.4、JWT To configure

2.4.1、accessToken turn JwtToken Configuration class

The main job is to create JwtAccessTokenConverter And set the key , And injected into the Bean Manage container .

/**
* accessToken turn JwtToken To configure
*/
@Configuration
public class JwtTokenStoreConfig {
@Bean
public JwtTokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
// Set up jwt secret key
jwtAccessTokenConverter.setSigningKey("test_key");
return jwtAccessTokenConverter;
}
@Bean
public JwtTokenEnhancer jwtTokenEnhancer() {
return new JwtTokenEnhancer();
}
}
2.4.2、JwtToken Content expansion configuration class

When accessToken turn jwtToken when , If you want to add custom user information to the token , For example, login time , You can configure the following classes :

/**
* JwtToken Content expansion configuration class
* @author Lin
*/
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String, Object> map = new HashMap<>();
map.put("enhance", "enhance info");
((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(map);
return oAuth2AccessToken;
}
}

2.5、 To configure spring security

/**
* spring security Configuration class
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* Password encryption
*
* @return
*/
@Bean
public BCryptPasswordEncoder getPasswordEncode() {
return new BCryptPasswordEncoder();
}
/**
* Interface request authorization
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**", "/login/**","/logout/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}

2.6、 Realization UserDetailsService

Realization UserDetailService For login authentication , And password mode need to use .

@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String password = bCryptPasswordEncoder.encode("123456");
return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("permission1"));
}
}

establish User The entity classes are as follows ( Not necessary ):

public class User implements UserDetails {
private String username;
private String password;
private List<GrantedAuthority> authorities;
public User(String username, String password, List<GrantedAuthority> authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}

3、 Run the test

3.1、 Get authorization code

Direct access /oauth/authorize? Interface can get authorization code

In my project, the access path is as follows :

http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://www.baidu.com&scope=all

Browser access , Jump to http://localhost:8080/login.html Default landing page , Click login , to grant authorization :

image-20210519171414311

Jump to https://www.baidu.com/?code=XKee3V page ,XKee3v It's the authorization code .

3.2、 Get the token according to the authorization code pattern

utilize postman test , visit

http://localhost:8080/oauth/token

To configure Authorization Information , That is, the account and password of the login client ;

image-20210519175250709

To configure Body Information ,grant_type The parameter value of is authorization_code,authorization_code It is the authorization code mode ,code That is the authorization code obtained above .

image-20210519175644261

Run the test after configuration , return access_token and refresh_token, notice access_token Success turned into JwtToken.

image-20210519175909997

3.3、 Password mode

Password mode is a little simpler than authorization mode , No authorization code is required , Directly ignore the operation of obtaining authorization code above , Just change the configuration information a little bit .

Authorization The information doesn't need to be changed , modify Body Information , grant_type The parameter value of is changed to password, Represents password mode , Fill in login spring security Account and password of .

image-20210519180556700

3.4、 Refresh token

In the above I set up access_token The timeliness of the contract is 60 second , When access_token When the failure , Need basis refresh_token Get a new token .

The access path is as follows :

http://localhost:8080/oauth/token

Authorization The configuration information is as follows :

image-20210519181055985

Body Need configuration grant_type The parameter value of is refresh_token, On behalf of refresh token , And fill in the refresh_token Parameter values for . After visiting, you can get new access_token.

image-20210519181404842

3.5、 according to access_token Get resources

The access path is as follows :

http://localhost:8080/user/getCurrentUser

Header Request header to add Authorization Parameters , And set the parameter value to bearer+ Space + access_token, You can get the interface return value .

image-20210519181904047

4、 Reference material

Bili, Bili Spring Security course

Ruan Yifeng -OAuth2.0

Please bring the original link to reprint ,thank
Similar articles

2021-08-09

2021-08-09