OAuth2 Overview OAuth2 depends on the application scenario, These modes are classified into four types: Authorization Code Simplified Mode Resource owner password Credentials Client credentials In the project, we usually use the authorization code mode, which is the most complex mode among the four modes. Usually, microblog and QQ third-party login frequently appear in websites will adopt this mode. Oauth2 Authorization consists of the following two components: Authorization Server: authentication service Resource Server: Resource service In actual projects, the two services can be deployed on one server or separately. Here’s how to use it in conjunction with Spring Boot.

Build table

Client information can be stored in memory, redis, and databases. Redis and database storage are commonly used in real projects. This article uses a database. Spring 0Auth2 has designed the database tables and is immutable.

The script for creating the 0Auth2 database is as follows:

DROP TABLE IF EXISTS clientdetails; DROP TABLE IF EXISTS oauth_access_token; DROP TABLE IF EXISTS oauth_approvals; DROP TABLE IF EXISTS oauth_client_details; DROP TABLE IF EXISTS oauth_client_token; DROP TABLE IF EXISTS oauth_refresh_token;

CREATE TABLE clientdetails ( appId varchar(128) NOT NULL, resourceIds varchar(256) DEFAULT NULL, appSecret varchar(256) DEFAULT NULL, scope varchar(256) DEFAULT NULL, grantTypes varchar(256) DEFAULT NULL, redirectUrl varchar(256) DEFAULT NULL, authorities varchar(256) DEFAULT NULL, access_token_validity int(11) DEFAULT NULL, refresh_token_validity int(11) DEFAULT NULL, additionalInformation varchar(4096) DEFAULT NULL, autoApproveScopes varchar(256) DEFAULT NULL, PRIMARY KEY (appId) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE oauth_access_token ( token_id varchar(256) DEFAULT NULL, token blob, authentication_id varchar(128) NOT NULL, user_name varchar(256) DEFAULT NULL, client_id varchar(256) DEFAULT NULL, authentication blob, refresh_token varchar(256) DEFAULT NULL, PRIMARY KEY (authentication_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE oauth_approvals ( userId varchar(256) DEFAULT NULL, clientId varchar(256) DEFAULT NULL, scope varchar(256) DEFAULT NULL, status varchar(10) DEFAULT NULL, expiresAt datetime DEFAULT NULL, lastModifiedAt datetime DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE oauth_client_details ( client_id varchar(128) NOT NULL, resource_ids varchar(256) DEFAULT NULL, client_secret varchar(256) DEFAULT NULL, scope varchar(256) DEFAULT NULL, authorized_grant_types varchar(256) DEFAULT NULL, web_server_redirect_uri varchar(256) DEFAULT NULL, authorities varchar(256) DEFAULT NULL, access_token_validity int(11) DEFAULT NULL, refresh_token_validity int(11) DEFAULT NULL, additional_information varchar(4096) DEFAULT NULL, autoapprove varchar(256) DEFAULT NULL, PRIMARY KEY (client_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE oauth_client_token ( token_id varchar(256) DEFAULT NULL, token blob, authentication_id varchar(128) NOT NULL, user_name varchar(256) DEFAULT NULL, client_id varchar(256) DEFAULT NULL, PRIMARY KEY (authentication_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS oauth_code; CREATE TABLE oauth_code ( code varchar(256) DEFAULT NULL, authentication blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE oauth_refresh_token ( token_id varchar(256) DEFAULT NULL, token blob, authentication blob ) ENGINE=InnoDB DEFAULT CHARSET=utf8; For testing purposes, let’s insert a piece of client information.

INSERT INTO oauth_client_details VALUES (‘dev’, ”, ‘dev’, ‘app’, ‘password,client_credentials,authorization_code,refresh_token’, ‘www.baidu.com’, ”, 3600, 3600, ‘{“country”:”CN”,”country_code”:”086″}’, ‘false’); The table for users, permissions, and roles is as follows:

DROP TABLE IF EXISTS user; DROP TABLE IF EXISTS role; DROP TABLE IF EXISTS user_role; DROP TABLE IF EXISTS role_permission; DROP TABLE IF EXISTS permission;

CREATE TABLE user ( id bigint(11) NOT NULL AUTO_INCREMENT, username varchar(255) NOT NULL, password varchar(255) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE role ( id bigint(11) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE user_role ( user_id bigint(11) NOT NULL, role_id bigint(11) NOT NULL ); CREATE TABLE role_permission ( role_id bigint(11) NOT NULL, permission_id bigint(11) NOT NULL ); CREATE TABLE permission ( id bigint(11) NOT NULL AUTO_INCREMENT, url varchar(255) NOT NULL, name varchar(255) NOT NULL, description varchar(255) NULL, pid bigint(11) NOT NULL, PRIMARY KEY (id) );

INSERT INTO user (id, username, password) VALUES (1,’user’,’e10adc3949ba59abbe56e057f20f883e’); INSERT INTO user (id, username , password) VALUES (2,’admin’,’e10adc3949ba59abbe56e057f20f883e’); INSERT INTO role (id, name) VALUES (1,’USER’); INSERT INTO role (id, name) VALUES (2,’ADMIN’); INSERT INTO permission (id, url, name, pid) VALUES (1,’/’,”,0); INSERT INTO permission (id, url, name, pid) VALUES (2,’/’,”,0); INSERT INTO user_role (user_id, role_id) VALUES (1, 1); INSERT INTO user_role (user_id, role_id) VALUES (2, 2); INSERT INTO role_permission (role_id, permission_id) VALUES (1, 1); INSERT INTO role_permission (role_id, permission_id) VALUES (2, 2); The project structure

resources |____templates | |____login.html | |____application.yml java |____com | |____gf | | |____SpringbootSecurityApplication.java | | |____config | | | |____SecurityConfig.java | | | |____MyFilterSecurityInterceptor.java | | | |____MyInvocationSecurityMetadataSourceService.java | | | |____ResourceServerConfig.java | | | |____WebResponseExceptionTranslateConfig.java | | | |____AuthorizationServerConfiguration.java | | | |____MyAccessDecisionManager.java | | |____entity | | | |____User.java | | | |____RolePermisson.java | | | |____Role.java | | |____mapper | | | |____PermissionMapper.java | | | |____UserMapper.java | | | |____RoleMapper.java | | |____controller | | | |____HelloController.java | | | |____MainController.java | | |____service | | | |____MyUserDetailsService.java

XML org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-oauth2-client org.springframework.boot spring-boot-starter-oauth2-resource-server org.springframework.security.oauth.boot spring-security-oauth2-autoconfigure 2.1.3.RELEASE SecurityConfig Supports password mode To configure AuthenticationManager

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired private MyUserDetailsService userService; @ Override protected void the configure (AuthenticationManagerBuilder auth) throws the Exception {/ / check user auth. UserDetailsService ( UserService. PasswordEncoder(new passwordEncoder() {Override public String encode(CharSequence) charSequence) { System.out.println(charSequence.toString()); return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()); } @override public Boolean matches(CharSequence CharSequence, CharSequence) String s) { String encode = DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()); boolean res = s.equals( encode ); return res; }}); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.requestMatchers() .antMatchers("/oauth/**","/login","/login-error") .and() .authorizeRequests() .antMatchers("/oauth/**").authenticated() .and() .formLogin().loginPage( "/login" ).failureUrl( "/login-error" ); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception{ return super.authenticationManager(); } @Bean public PasswordEncoder passwordEncoder() { return new PasswordEncoder() { @Override public String encode(CharSequence charSequence) { return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return Objects.equals(charSequence.toString(),s); }}; }Copy the code

} AuthorizationServerConfiguration authentication server configuration

/ * *

  • Authentication server Configuration * / @ Configuration @ EnableAuthorizationServer public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    / * *

    • Grant type */ @autoWired Private AuthenticationManager AuthenticationManager;

    / * *

    • */ @autoWired Private MyUserDetailsService userDetailsService;

    / * *

    • */ @autowired private DataSource DataSource;

    / * *

    • */ @autoWired Private TokenStore TokenStore;

    @Autowired private WebResponseExceptionTranslator webResponseExceptionTranslator;

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

    @ Override public void the configure (AuthorizationServerSecurityConfigurer security) throws the Exception {/ * * * configuration oauth2 cross-domain/service CorsConfigurationSource source = new CorsConfigurationSource() { @Override public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedHeader(“”); corsConfiguration.addAllowedOrigin(request.getHeader( HttpHeaders.ORIGIN)); corsConfiguration.addAllowedMethod(“*”); corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); return corsConfiguration; }};

     security.tokenKeyAccess("permitAll()")
             .checkTokenAccess("permitAll()")
             .allowFormAuthenticationForClients()
             .addTokenEndpointAuthenticationFilter(new CorsFilter(source));
    Copy the code

    }

    @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource); }

    @ Override public void the configure (AuthorizationServerEndpointsConfigurer endpoints) throws the Exception {/ / password authentication type endpoints.authenticationManager(authenticationManager); // Configure the token storage mode endPoints. TokenStore (tokenStore); / / custom login or authentication failed to return information endpoints. The exceptionTranslator (webResponseExceptionTranslator); / / to use refresh_token, need additional configuration userDetailsService endpoints. The userDetailsService (userDetailsService);

    }

} ResourceServerConfig Resource server configuration

/ * *

  • */ @Configuration@enableresourceserver Public Class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    / * *

    • Set the URL that requires token authentication
    • The url can screen out in WebSecurityConfigurerAdapter,
    • For the same URL, if authentication is configured for both
    • Enter the ResourceServerConfigurerAdapter, will be the priority for token authentication. It’s not going to
    • WebSecurityConfigurerAdapter basic auth or forms authentication. */ @Override public void configure(HttpSecurity http) throws Exception { http.requestMatchers().antMatchers(“/hi”) .and() .authorizeRequests() .antMatchers(“/hi”).authenticated(); }

} key code is these, other class code refer to the source code address provided below.

Verify the password authorization mode. [Password mode requires parameters: username, password, grant_type, client_id, client_secret]

The request token

curl -X POST -d “username=admin&password=123456&grant_type=password&client_id=dev&client_secret=dev” Return to http://localhost:8080/oauth/token

{ “access_token”: “d94ec0aa-47ee-4578-b4a0-8cf47f0e8639”, “token_type”: “bearer”, “refresh_token”: “23503BC7-4494-4795-A047-98DB75053374 “,” expiRES_IN “: 3475, “scope”: “app”} Do not carry token to access resources,

curl http://localhost:8080/hi? Name =zhangsan An unauthorized message is displayed

{“error”: “unauthorized”, “error_description”: “Full authentication is required to access this resource”} Access resources with a token

curl http://localhost:8080/hi? Name = zhangsan&Access _token=164471f7-6fc6-4890-b5d2-eb43bda3328a The output is correct

Hi, Zhangsan refreshing token

curl -X POST -d ‘grant_type=refresh_token&refresh_token=23503bc7-4494-4795-a047-98db75053374&client_id=dev&client_secret=dev’ Return to http://localhost:8080/oauth/token

{ “access_token”: “ef53eb01-eb9b-46d8-bd58-7a0f9f44e30b”, “token_type”: “bearer”, “refresh_token”: “23503bc7-4494-4795-a047-98db75053374”, “expires_in”: 3599, “scope”: “App”} Client authorization mode [Client mode requires parameters: grant_type, client_id, client_secret]

The request token

The curl -x POST – d “grant_type = client_credentials & client_id = dev&client _secret = dev” http://localhost:8080/oauth/token to return

{ “access_token”: “a7be47b3-9dc8-473e-967a-c7267682dc66”, “token_type”: “bearer”, “expires_in”: 3564, “scope”: “App”} License code mode to obtain code

Access the following address in the browser:

Jump to the login page, http://localhost:8080/oauth/authorize?response_type=code&client_id=dev&redirect_uri=http://www.baidu.com Enter your account and password for authentication:

Change a token by code

curl -X POST -d “grant_type=authorization_code&code=qS03iu&client_id=dev&client_secret=dev&redirect_uri=http://www.baidu.com” http://localhost:8080/oauth/token

return

{ “access_token”: “90a246fa-a9ee-4117-8401-ca9c869c5be9”, “token_type”: “bearer”, “refresh_token”: “23503bc7-4494-4795-a047-98db75053374”, “expires_in”: 3319, “scope”: “app” }