oauth2.0 authorization code mode
Welcome to the "Java master" of the blogger official account, focusing on dry cargo articles in Java field. http://www.javaman.cn/sb2/oauth-code
Authorization code means that a third-party application first applies for an authorization code, and then uses the code to obtain a token.
This method is the most commonly used process and has the highest security. It is suitable for Web applications with back-end. The authorization code is transmitted through the front end, the token is stored in the back end, and all communication with the resource server is completed in the back end. This separation of front and rear ends can avoid token leakage.
1. Authorization code mode process
In the first step, website A provides A link. After clicking, the user will jump to website B and authorize the user data to website A. The following is A schematic link from website A to website B.
https://b.com/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
In the above URL, response_ The type parameter indicates that it is required to return the authorization code, client_ The ID parameter lets B know who is requesting and redirect_ The URI parameter is the jump URL after B accepts or rejects the request, and the scope parameter indicates the required authorization range (read-only here).
Step 2: after the user jumps, website B will ask the user to log in, and then ask whether he agrees to grant authorization to website A. When the user agrees, website B will jump back to redirect_ The URL specified by the URI parameter. When jumping, an authorization code will be returned, as shown below.
https://a.com/callback?code=AUTHORIZATION_CODE
In the above URL, the code parameter is the authorization code.
Third, after website A gets the authorization code, it can request A token from website B at the back end.
https://b.com/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL
In the above URL, client_id parameter and client_ The secret parameter is used to let B confirm the identity of A (the client_secret parameter is confidential, so it can only send requests at the back end). Grant_ The value of the type parameter is AUTHORIZATION_CODE indicates that the authorization method adopted is the authorization code, and the code parameter is the authorization code obtained in the previous step, redirect_ The URI parameter is the callback URL after the token is issued.
Step 4: after receiving the request, website B will issue a token. The specific method is to report to redirect_uri to send a piece of JSON data.
{ "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", "uid":100101, "info":{...} }
In the JSON data above, access_ The token field is the token. Website A gets it at the back end.
2. Authorization code mode implementation code
2.1 create POM xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dashi</groupId> <artifactId>springsecurity-oauth</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springsecurity-oauth</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR5</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <!--security rely on--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <!--boot rely on--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--boot rely on--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--test rely on--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
2.2 create spring security configuration file
package com.dashi.springsecurityoauth.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/oauth/**","/login/**","/logout/**") .permitAll() .anyRequest() .authenticated() .and() .formLogin() .permitAll(); } }
2.3 create UserService and implement UserDetailService interface
package com.dashi.springsecurityoauth.model; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; 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 this.authorities; } @Override public String getPassword() { return this.password; } @Override public String getUsername() { return this.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; } }
2.4 creating authentication services
package com.dashi.springsecurityoauth.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("admin") .secret(passwordEncoder.encode("654321")) .accessTokenValiditySeconds(3600) .redirectUris("http://www.baidu.com") .scopes("all") //Configure grant_type indicates authorization code .authorizedGrantTypes("authorization_code"); } }
2.5 creating resource services
package com.dashi.springsecurityoauth.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest() .authenticated() .and() .requestMatchers() //Addresses starting with / user access resources according to the token .antMatchers("/user/**"); } }
2.6 start service access address
2.7 in the previous step, the connection jumps to the input user name and address
2.8 click the resources allowed to be accessed and jump to the authorized website( http://www.baidu.com ), get authorization code
2.9 open postman, fill in the following contents and get the token
2.10 accessing protected resources through token
Reference documents: Four ways of OAuth 2.0 - ruanyifeng's Weblog (ruanyifeng.com)