The core of Spring security is a set of filter chains. Project launch on autoconfig.
The core is the Basic Authentication Filter used to authenticate the user's identity;
One filter handles one authentication mode;
For the username password authentication filter,
- Will check if it is a login request,
- Whether to include username and password (that is, some authentication information required by the filter)
- If not, release to next
The next information to determine whether it is necessary according to their own responsibilities,
Basic is characterized by Authorization:Basic eHh4Onh4 information in the request header
There may be more certified filters in the middle. The last step is the filter security interceptor,
It will be determined whether the request can access the rest Service Based on the configuration in BrowserSecurityConfig;
If rejected, a different exception will be thrown (depending on the reason).
Exception Translation Filter will catch the thrown errors, and then prompt the return of information according to different authentication methods
Note: the green filter can be configured to be effective or not, and other filters cannot be controlled;
The above is the basic principle of security. Other derivative functions are based on this shelf
How to handle exceptions thrown in the ExceptionTranslationFilter?
package com.healthy.security.server.handler; import com.healthy.security.core.support.SimpleResponse; import com.healthy.security.server.handler.exception.HealthyOauthException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.web.util.ThrowableAnalyzer; import org.springframework.stereotype.Component; import org.springframework.web.HttpRequestMethodNotSupportedException; import java.io.IOException; import java.nio.file.AccessDeniedException; /** * healthy translator that converts exceptions into {@link OAuth2Exception}s. The output matches the OAuth 2.0 * specification in terms of error response format and HTTP status code. */ @Slf4j @Component("healthyResponseExceptionTranslator") public class HealthyResponseExceptionTranslator implements WebResponseExceptionTranslator<SimpleResponse> { private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer(); @Override public ResponseEntity<SimpleResponse> translate(Exception e) throws Exception { // Try to extract a SpringSecurityException from the stacktrace Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e); // Exception stack get OAuth2Exception exception Exception exception = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(OAuth2Exception.class, causeChain); // OAuth2Exception in exception stack if (exception != null) { return handleOAuth2Exception((OAuth2Exception) exception); } exception = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain); if (exception != null) { return handleOAuth2Exception(new HealthyOauthException(e.getMessage(), e)); } exception = (AccessDeniedException) throwableAnalyzer .getFirstThrowableOfType(AccessDeniedException.class, causeChain); if (exception instanceof AccessDeniedException) { return handleOAuth2Exception(new HealthyOauthException(exception.getMessage(), exception)); } exception = (HttpRequestMethodNotSupportedException) throwableAnalyzer .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain); if (exception instanceof HttpRequestMethodNotSupportedException) { return handleOAuth2Exception(new HealthyOauthException(exception.getMessage(), exception)); } exception = (UsernameNotFoundException) throwableAnalyzer .getFirstThrowableOfType(UsernameNotFoundException.class, causeChain); if (exception instanceof UsernameNotFoundException) { return handleOAuth2Exception(new HealthyOauthException(exception.getMessage(), exception)); } // Server internal error if the above exception is not included return handleOAuth2Exception(new HealthyOauthException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), e)); } private ResponseEntity<SimpleResponse> handleOAuth2Exception(OAuth2Exception e) throws IOException { int status = e.getHttpErrorCode(); HttpHeaders headers = new HttpHeaders(); headers.set("Cache-Control", "no-store"); headers.set("Pragma", "no-cache"); if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) { headers.set("WWW-Authenticate", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary())); } SimpleResponse simpleResponse = new SimpleResponse(e.getMessage()); return new ResponseEntity<SimpleResponse>(simpleResponse, headers, HttpStatus.valueOf(status)); } }
package com.healthy.security.server.handler.exception; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; public class HealthyOauthException extends OAuth2Exception { public HealthyOauthException(String msg, Throwable t) { super(msg, t); } public HealthyOauthException(String msg) { super(msg); } }
package com.healthy.security.server; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; /** * Authentication server configuration */ @Configuration @EnableAuthorizationServer public class HealthyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // ... omission @Autowired private WebResponseExceptionTranslator healthyResponseExceptionTranslator; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .exceptionTranslator(healthyResponseExceptionTranslator); } // ... omission }