The first two articles have experienced the of Spring Authorization Server respectively use And explained its various aspects filter The role of. Today, let's talk about the configuration of the Spring Authorization Server authorization server. It is strongly recommended that you try to build it manually. You will feel shallow on paper and know that you should practice it. Improving your code is the only way to improve your programming skills, which is the significance of this tutorial.
Configuration dependency
First, create a Spring Boot Servlet Web project, which is not difficult and will not be repeated. To integrate Spring Authorization Server, you need to introduce:
<!-- spring security starter must --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <!-- Current version --> <version>0.2.0</version> </dependency>
OAuth2.0 Client needs to register with the authorization server and persist. Spring Authorization Server provides JDBC implementation. See JdbcRegisteredClientRepository. For the convenience of demonstration, I use H2 database, which requires the following dependencies:
<!-- jdbc It must be imported, or it will be implemented by itself --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency>
❝ in production, you can switch to other relational databases. The database script is in Getting started with Spring Authorization Server In the DEMO of a text.
Spring Authorization Server configuration
Next is the configuration of Spring Authorization Server.
Filter chain configuration
According to the disassembly of the filter chain in the previous article, we need to inject some specific filters into the filter chain of Spring Security. These filters are configured by oauth2authorizationserverconfigurator < httpsecurity >. The following is the default configuration:
void defaultOAuth2AuthorizationServerConfigurer(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer<>(); // TODO, you can personalize the authorization server configurator according to your needs RequestMatcher authorizationServerEndpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher(); // Intercept request endpoints related to the authorization server http.requestMatcher(authorizationServerEndpointsMatcher) .authorizeRequests().anyRequest().authenticated().and() // Ignore the csrf of the relevant endpoint .csrf(csrf -> csrf.ignoringRequestMatchers(authorizationServerEndpointsMatcher)) // Open form login .formLogin() .and() // Configuration of application authorization server .apply(authorizationServerConfigurer); }
❝ you can call the configuration method provided by oauth2authorizationserverconfigurer < httpsecurity > for some personalized configuration.
OAuth2.0 client information persistence
This information will be persisted to the database. Spring Authorization Server provides three DDL scripts. In the introductory tutorial DEMO , H2 will automatically initialize and execute these DDL scripts. If you switch to Mysql and other databases, you may need to execute them yourself.
Client configuration information registration
The authorization server requires that the client must be registered to avoid illegal clients from initiating authorization applications. Just like you usually go to some open platforms to apply for a ClientID and Secret. The following is the definition script:
CREATE TABLE oauth2_registered_client ( id varchar(100) NOT NULL, client_id varchar(100) NOT NULL, client_id_issued_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, client_secret varchar(200) NULL, client_secret_expires_at timestamp NULL, client_name varchar(200) NOT NULL, client_authentication_methods varchar(1000) NOT NULL, authorization_grant_types varchar(1000) NOT NULL, redirect_uris varchar(1000) NULL, scopes varchar(1000) NOT NULL, client_settings varchar(2000) NOT NULL, token_settings varchar(2000) NOT NULL, PRIMARY KEY (id) );
The corresponding Java class is RegisteredClient:
public class RegisteredClient implements Serializable { private static final long serialVersionUID = Version.SERIAL_VERSION_UID; private String id; private String clientId; private Instant clientIdIssuedAt; private String clientSecret; private Instant clientSecretExpiresAt; private String clientName; private Set<ClientAuthenticationMethod> clientAuthenticationMethods; private Set<AuthorizationGrantType> authorizationGrantTypes; private Set<String> redirectUris; private Set<String> scopes; private ClientSettings clientSettings; private TokenSettings tokenSettings; // ellipsis }
Defining a client can be realized through the following Builder methods:
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) // Unique client ID and password .clientId("felord-client") .clientSecret("secret") // The name cannot be defined .clientName("felord") // Authorization method .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) // Authorization type .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) // The callback address list will be rejected if it is not in this column, and can only use IP or domain name, not localhost .redirectUri("http://127.0.0.1:8080/login/oauth2/code/felord-oidc") .redirectUri("http://127.0.0.1:8080/authorized") .redirectUri("http://127.0.0.1:8080/foo/bar") .redirectUri("https://baidu.com") // OIDC support .scope(OidcScopes.OPENID) // Other Scope .scope("message.read") .scope("message.write") // JWT configuration items include whether TTL reuses refreshToken, etc .tokenSettings(TokenSettings.builder().build()) // Configure the configuration items related to the client, including the authentication key or whether the authorization page is required .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) .build();
The RegisteredClient persisted to the database is represented by JSON as:
{ "id": "658cd010-4d8c-4824-a8c7-a86b642299af", "client_id": "felord-client", "client_id_issued_at": "2021-11-11 18:01:09", "client_secret": "{bcrypt}$2a$10$XKZ8iUckDcdQWnqw682zV.DVyGuov8Sywx1KyAn4tySsw.Jtltg0.", "client_secret_expires_at": null, "client_name": "felord", "client_authentication_methods": "client_secret_basic", "authorization_grant_types": "refresh_token,client_credentials,authorization_code", "redirect_uris": "http://127.0.0.1:8080/foo/bar,http://127.0.0.1:8080/authorized,http://127.0.0.1:8080/login/oauth2/code/felord-oidc,https://baidu.com", "scopes": "openid,message.read,message.write", "client_settings": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.client.require-proof-key\":false,\"settings.client.require-authorization-consent\":true}", "token_settings": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.token.reuse-refresh-tokens\":true,\"settings.token.id-token-signature-algorithm\":[\"org.springframework.security.oauth2.jose.jws.SignatureAlgorithm\",\"RS256\"],\"settings.token.access-token-time-to-live\":[\"java.time.Duration\",300.000000000],\"settings.token.refresh-token-time-to-live\":[\"java.time.Duration\",3600.000000000]}" }
❝ note that the above configuration is closely related to the configuration of your OAuth2.0 client application.
Now that the table is persistent, you naturally need to operate the JDBC service interface of the table, which is RegisteredClientRepository. We need to declare an implementation as Spring Bean. Here, choose the JDBC based implementation:
@Bean public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) { return new JdbcRegisteredClientRepository(jdbcTemplate); }
Don't forget to call the save(RegisteredClient) method to persist the client information that needs to be registered.
❝ the implementation relies on the spring boot starter JDBC class library. You can also use Mybatis to implement it.
OAuth2 authorization information persistence
Record the authorization record of the authorized Resource Owner to a client. The corresponding Java class is OAuth2Authorization. The following is the definition script:
CREATE TABLE oauth2_authorization ( id varchar(100) NOT NULL, registered_client_id varchar(100) NOT NULL, principal_name varchar(200) NOT NULL, authorization_grant_type varchar(100) NOT NULL, attributes varchar(4000) NULL, state varchar(500) NULL, authorization_code_value blob NULL, `authorization_code_issued_at` timestamp NULL, authorization_code_expires_at timestamp NULL, authorization_code_metadata varchar(2000) NULL, access_token_value blob NULL, access_token_issued_at timestamp NULL, access_token_expires_at timestamp NULL, access_token_metadata varchar(2000) NULL, access_token_type varchar(100) NULL, access_token_scopes varchar(1000) NULL, oidc_id_token_value blob NULL, oidc_id_token_issued_at timestamp NULL, oidc_id_token_expires_at timestamp NULL, oidc_id_token_metadata varchar(2000) NULL, refresh_token_value blob NULL, refresh_token_issued_at timestamp NULL, refresh_token_expires_at timestamp NULL, refresh_token_metadata varchar(2000) NULL, PRIMARY KEY (id) );
❝ the mechanism here has not been studied yet. Dig a pit first.
Similarly, it also needs a persistent service interface OAuth2AuthorizationService and injects Spring IoC:
/** * Manage OAuth2 authorization information services * * @param jdbcTemplate the jdbc template * @param registeredClientRepository the registered client repository * @return the o auth 2 authorization service */ @Bean public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) { return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository); }
OAuth2Authorization persisted to the database is represented in JSON as:
{ "id": "aa2f6e7d-d9b9-4360-91ef-118cbb6d4b09", "registered_client_id": "658cd010-4d8c-4824-a8c7-a86b642299af", "principal_name": "felord", "authorization_grant_type": "authorization_code", "attributes": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest\":{\"@class\":\"org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest\",\"authorizationUri\":\"http://localhost:9000/oauth2/authorize\",\"authorizationGrantType\":{\"value\":\"authorization_code\"},\"responseType\":{\"value\":\"code\"},\"clientId\":\"felord-client\",\"redirectUri\":\"http://127.0.0.1:8080/foo/bar\",\"scopes\":[\"java.util.Collections$UnmodifiableSet\",[\"message.read\",\"message.write\"]],\"state\":\"9gTcVNXgV8Pn_Ron3bkFb6M92AYCodeWKoEd6xxaiUg=\",\"additionalParameters\":{\"@class\":\"java.util.Collections$UnmodifiableMap\"},\"authorizationRequestUri\":\"http://localhost:9000/oauth2/authorize?response_type=code&client_id=felord-client&scope=message.read%20message.write&state=9gTcVNXgV8Pn_Ron3bkFb6M92AYCodeWKoEd6xxaiUg%3D&redirect_uri=http://127.0.0.1:8080/foo/bar\",\"attributes\":{\"@class\":\"java.util.Collections$UnmodifiableMap\"}},\"java.security.Principal\":{\"@class\":\"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\",\"authorities\":[\"java.util.Collections$UnmodifiableRandomAccessList\",[{\"@class\":\"org.springframework.security.core.authority.SimpleGrantedAuthority\",\"authority\":\"ROLE_USER\"}]],\"details\":{\"@class\":\"org.springframework.security.web.authentication.WebAuthenticationDetails\",\"remoteAddress\":\"0:0:0:0:0:0:0:1\",\"sessionId\":\"FD624F1AD55A2418CC9815A86AA32696\"},\"authenticated\":true,\"principal\":{\"@class\":\"org.springframework.security.core.userdetails.User\",\"password\":null,\"username\":\"felord\",\"authorities\":[\"java.util.Collections$UnmodifiableSet\",[{\"@class\":\"org.springframework.security.core.authority.SimpleGrantedAuthority\",\"authority\":\"ROLE_USER\"}]],\"accountNonExpired\":true,\"accountNonLocked\":true,\"credentialsNonExpired\":true,\"enabled\":true},\"credentials\":null},\"org.springframework.security.oauth2.server.authorization.OAuth2Authorization.AUTHORIZED_SCOPE\":[\"java.util.Collections$UnmodifiableSet\",[\"message.read\",\"message.write\"]]}", "state": null, "authorization_code_value": "EZFxDcsKoaGtyqRTS0oNMg85EcVcyLdVssuD3SV-o0FvNXsSTRjTmCdu0ZPZnVIQ7K4TTSzrvLwBqoRXOigo_dWVNeqE44LjHHL_KtujM_Mxz8hLZgGhtfipvTdpWWR1", "authorization_code_issued_at": "2021-11-11 18:44:45", "authorization_code_expires_at": "2021-11-11 18:49:45", "authorization_code_metadata": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"metadata.token.invalidated\":true}", "access_token_value": "eyJ4NXQjUzI1NiI6IlZGR1F4Q21nSEloX2dhRi13UGIxeEM5b0tBMXc1bGEwRUZtcXFQTXJxbXciLCJraWQiOiJmZWxvcmRjbiIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJmZWxvcmQiLCJhdWQiOiJmZWxvcmQtY2xpZW50IiwibmJmIjoxNjM2NjI3NDg0LCJzY29wZSI6WyJtZXNzYWdlLnJlYWQiLCJtZXNzYWdlLndyaXRlIl0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjM2NjI3Nzg0LCJpYXQiOjE2MzY2Mjc0ODR9.CFzye9oIh8-ZMpyp9XoIXIQLnj2Sn17yZ9bgn7NYAbrp2hRq-Io_Se2SJpSEMa_Ce44aOGmcLTmIOILYUxlU08QCtHgr4UfCZttzroQhEn3Qui7fixBMprPYqxmu2KL5G_l3q5EWyh4G0ilHpByCBDeBGAl7FpaxSDlelnBfNGs9q6nJCs7aC40U_YPBRLoCBLVK1Y8t8kQvNu8NqCkS5D5DZAogpmlVg7jSIPz1UXVIh7iDTTQ1wJl6rZ1E87E0UroX4eSuYfMQ351y65IUlB14hvKhu03yDLTiVKtujOo3m0DAkJTbk3ZkFZEmDf4N3Yn-ktU7cyswQWa1bKf3og", "access_token_issued_at": "2021-11-11 18:44:45", "access_token_expires_at": "2021-11-11 18:49:45", "access_token_metadata": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"metadata.token.claims\":{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"sub\":\"felord\",\"aud\":[\"java.util.Collections$SingletonList\",[\"felord-client\"]],\"nbf\":[\"java.time.Instant\",1636627484.674000000],\"scope\":[\"java.util.Collections$UnmodifiableSet\",[\"message.read\",\"message.write\"]],\"iss\":[\"java.net.URL\",\"http://localhost:9000\"],\"exp\":[\"java.time.Instant\",1636627784.674000000],\"iat\":[\"java.time.Instant\",1636627484.674000000]},\"metadata.token.invalidated\":false}", "access_token_type": "Bearer", "access_token_scopes": "message.read,message.write", "oidc_id_token_value": null, "oidc_id_token_issued_at": null, "oidc_id_token_expires_at": null, "oidc_id_token_metadata": null, "refresh_token_value": "hbD9dVMpu855FhDDOYapwsQSx8zO9iPX5LUZKeXWzUcbE2rgYRV-sgXl5vGwyByLNljcqVyK9Pgquzbcoe6dkt0_yPQPJfxLY8ezEQ-QREBjxNYqecd6OI9SHMQkBObG", "refresh_token_issued_at": "2021-11-11 18:44:45", "refresh_token_expires_at": "2021-11-11 19:44:45", "refresh_token_metadata": "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"metadata.token.invalidated\":false}" }
❝ the stored things are relatively complete, and even serialize Java classes.
Confirm authorization persistence
The persistence of the authorization confirmation information oauthauthorizationconstraint by the Resource Owner is relatively simple. The following is the definition script:
CREATE TABLE oauth2_authorization_consent ( registered_client_id varchar(100) NOT NULL, principal_name varchar(200) NOT NULL, authorities varchar(1000) NOT NULL, PRIMARY KEY (registered_client_id, principal_name) );
The corresponding persistence service interface is OAuth2AuthorizationConsentService, which should also be injected with Spring IoC:
@Bean public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) { return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository); }
The oauth2authorizationconstraint persisted to the database is represented in JSON as:
{ "registered_client_id": "658cd010-4d8c-4824-a8c7-a86b642299af", "principal_name": "felord", "authorities": "SCOPE_message.read,SCOPE_message.write" }
JWK
The full name of JWK is JSON Web Key. It is a specification that describes the encrypted key with JSON objects. It is the same as JWT JOSE specification An important part of. Refer to JWK documents for detailed definitions of specifications. JWK reference example:
{ "keys": [ { "kty": "RSA", "x5t#S256": "VFGQxCmgHIh_gaF-wPb1xC9oKA1w5la0EFmqqPMrqmw", "e": "AQAB", "kid": "felordcn", "x5c": [ "MIIDczCCAlugAwIBAgIEURwmYzANBgkqhkiG9w0BAQsFADBqMQ0wCwYDVQQGEwQoY24pMQ0wCwYDVQQIEwQoaG4pMQ0wCwYDVQQHEwQoenopMRMwEQYDVQQKEwooZmVsb3JkY24pMRMwEQYDVQQLEwooZmVsb3JkY24pMREwDwYDVQQDEwgoRmVsb3JkKTAeFw0yMTEwMTgwNDUwMTRaFw0yMjEwMTgwNDUwMTRaMGoxDTALBgNVBAYTBChjbikxDTALBgNVBAgTBChobikxDTALBgNVBAcTBCh6eikxEzARBgNVBAoTCihmZWxvcmRjbikxEzARBgNVBAsTCihmZWxvcmRjbikxETAPBgNVBAMTCChGZWxvcmQpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgo0TPk1td7iROmmLcGbOsZ2F68kTertDwRyk+leqBl+qyJAkjoVgVaCRRQHZmvu/YGp93vOaEd/zFdVj/rFvMXmwBxgYPOeSG0bHkYtFBaUiLf1vhW5lyiPHcGide3uw1p+il3JNiOpcnLCbAKZgzm4qaugeuOD02/M0YcMW2Jqg3SUWpC+9vu9yt5dVc1xpmpwEAamKzvynI3Zxl44ddlA8RRAS6kV0OUcKbEG63G3yZ4MHnhrFrZDuvlwfSSgn0wFOC/b6mJ+bUxByMAXKD0d4DS2B2mVl7RO5AzL4SFcqtZZE3Drtcli67bsENyOQeoTVaKO6gu5PEEFlQ7pHKwIDAQABoyEwHzAdBgNVHQ4EFgQUqbLZ76DtdEEpTZUcgP7LsdGk8/AwDQYJKoZIhvcNAQELBQADggEBAEzfhi6/B00NxSPKAYJea/0MIyHr4X8Ue6Du+xl2q0UFzSkyIiMcPNmOYW5L1PWGjxR5IIiUgxKI5bEvhLkHhkMV+GRQSPKJXeC3szHdoZ3fXDZnuC0I88a1YDsvzuVhyjLL/n5lETRT4QWo5LsAj5v7AX+p46HM0iqSyTptafm2wheEosFA3ro4+vEDRaMrKLY1KdJuvvrrQIRpplhB/JbncmjWrEEvICSLEXm+kdGFgWNXkNxF0PhTLyPu3tEb2xLmjFltALwi3KPUGv9zVjxb7KyYiMnVsOPnwpDLOyREM9j4RLDiwf0tsCqPqltVExvFZouoL26fhcozfcrqC70=" ], "n": "go0TPk1td7iROmmLcGbOsZ2F68kTertDwRyk-leqBl-qyJAkjoVgVaCRRQHZmvu_YGp93vOaEd_zFdVj_rFvMXmwBxgYPOeSG0bHkYtFBaUiLf1vhW5lyiPHcGide3uw1p-il3JNiOpcnLCbAKZgzm4qaugeuOD02_M0YcMW2Jqg3SUWpC-9vu9yt5dVc1xpmpwEAamKzvynI3Zxl44ddlA8RRAS6kV0OUcKbEG63G3yZ4MHnhrFrZDuvlwfSSgn0wFOC_b6mJ-bUxByMAXKD0d4DS2B2mVl7RO5AzL4SFcqtZZE3Drtcli67bsENyOQeoTVaKO6gu5PEEFlQ7pHKw" } ] }
❝ the significance of JWK is to generate JWT and provide JWK endpoint to OAuth2.0 resource server to decode and verify JWT.
Public private key
JWK will involve the encryption algorithm. Here, RSASHA256 algorithm is used as the encryption algorithm, and the. jks public-private key certificate file is generated through the Keytool tool. Of course, you can also generate certificates in pkcs12 format through openssl. The generated method has been described in Spring Security practical dry goods, and will not be repeated here.
JWKSource
Since the JOSE implementation of Spring Security relies on nimbus JOSE JWT, we only need to implement jwksource < C extends securitycontext > and inject Spring IoC. Relevant codes are as follows:
/** * Load JWK resources * * @return the jwk source */ @SneakyThrows @Bean public JWKSource<SecurityContext> jwkSource() { //TODO is optimized to configuration here // Path to certificate String path = "felordcn.jks"; // Certificate alias String alias = "felordcn"; // keystore password String pass = "123456"; ClassPathResource resource = new ClassPathResource(path); KeyStore jks = KeyStore.getInstance("jks"); // KeyStore pkcs12 = KeyStore.getInstance("pkcs12"); char[] pin = pass.toCharArray(); jks.load(resource.getInputStream(), pin); RSAKey rsaKey = RSAKey.load(jks, alias, pin); JWKSet jwkSet = new JWKSet(rsaKey); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); }
Authorization server meta information configuration
The client information RegisteredClient contains the Token configuration item TokenSettings and the client configuration item ClientSettings. The authorization server itself also provides a configuration tool to configure its meta information. Most of us use the default configuration. In fact, the only thing that needs to be configured is the address issuer of the authorization server. In DEMO, although I use localhost:9000, the issuer has no problem, but in production, this place should be configured as a domain name.
/** * Configuring OAuth2.0 provider meta information * * @return the provider settings */ @Bean public ProviderSettings providerSettings(@Value("${server.port}") Integer port) { //TODO production should use domain names return ProviderSettings.builder().issuer("http://localhost:" + port).build(); }
❝ you can modify the local hosts file and try using the domain name.
At this point, the configuration of the Spring Authorization Server has been completed, but the configuration of the entire authorization server has not been completed.
Authorization server security configuration
The above is the configuration of the authorization server itself. The security configuration of the authorization server itself is undertaken by another filter chain. We also need to configure it, which is a conventional Spring Security configuration. Here is a simple configuration, which is also the configuration in DEMO:
@EnableWebSecurity(debug = true) public class DefaultSecurityConfig { // @formatter:off @Bean SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated() ) .formLogin(); return http.build(); } // @formatter:on /** * Abstract a Spring Security security security user {@ link User} in memory, and the user is also a Resource Owner; * In actual development, it needs to be persisted to the database. * * @return the user details service */ // @formatter:off @Bean UserDetailsService users() { UserDetails user = User.builder() .username("felord") .password("password") .passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder()::encode) .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } // @formatter:on /** * Open access control for some endpoints. * * If you use programs that rely on these endpoints, such as consult health check; * Open the H2 database web console access control to facilitate you to view the data. See the description of the configuration file for details. * * @return the web security customizer */ @Bean WebSecurityCustomizer webSecurityCustomizer() { return web -> web.ignoring().antMatchers("/actuator/health","/h2-console/**"); } }
Here, an authorization server based on Spring Authorization Server is set up. In the next article, we will implement the login function of OAuth2.0. Please look forward to it.
Dispel doubts
❝ why is a project configured with two or more securityfilterchains?
The reason why there are two securityfilterchains is that the programming should ensure a single responsibility, whether it is the underlying architecture or business code. Therefore, HttpSecurity is injected into Spring IoC with a prototype based Spring Bean. For the two filter chains in this application, they are the filter chain of authorization server and the filter chain of application security. In fact, they do not have much contact with each other.