Summary
AccessDeniedHandler and AuthenticationEntryPoint do not work because the global exception handler is defined
Actual Behavior
When the request has an AuthenticationException or an AccessDeniedException, it does not enter my custom AccessDeniedHandler and AuthenticationEntryPoint.
1、Access to protected resources 2、Console prints AccessDeniedException,it does not enter my custom AccessDeniedHandler 3、I found it into my custom global exception handler.
Expected Behavior
enter my custom AccessDeniedHandler or AuthenticationEntryPoint
Configuration
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<?> exception(Exception exception) throws Exception {
log.error(exception.getMessage(), exception);
return ResponseEntity.ok("系统繁忙,请稍后再试!");
}
}
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private StaticHeadersWriter staticHeadersWriter;
{
List<Header> headers = new ArrayList<>();
headers.add(new Header("Access-Control-Allow-Origin", "*"));
headers.add(new Header("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACES"));
headers.add(new Header("Access-Control-Allow-Headers", Security.TOKEN));
staticHeadersWriter = new StaticHeadersWriter(headers);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/swagger-ui.html",
"/swagger-resources/**",
"/webjars/**",
"/v2/api-docs")
.permitAll()
.anyRequest()
.authenticated()
.and()
.addFilterAt(new UsernamePasswordAuthenticationFilter(authenticationManager()), org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new OptionsRequestFilter(), HeaderWriterFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new CustomizedAuthenticationEntryPoint())
.accessDeniedHandler(new CustomizedAccessDeniedHandler())
.and()
.headers()
.addHeaderWriter(staticHeadersWriter)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable()
.logout()
.disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(new JwtAuthenticationProvider())
.userDetailsService(userService)
.passwordEncoder(passwordEncoder)
;
}
}
Version
spring-boot-starter-security 2.1.5.RELEASE
Sample
Additional
From the log printed by the console, I guess if the AccessDeniedException thrown by the MethodSecurityInterceptor when calling the beforeInvocation method is caught by the global exception handler, causing the superior ExceptionTranslationFilter to not catch the exception.
Comment From: citygs
I got the same problem,how to fix this bug?
Comment From: allurx
@citygs
Currently I can only throw the exception caught by the global exception handler up, and then AccessDeniedHandler and AuthenticationEntryPoint can catch this exception. You can check out the handler in spring-security-demo I wrote earlier.GlobalExceptionHandler
Comment From: rwinch
There really isn't anything we can do on our side. It might be that users actually want to catch the exception and process it. Instead we recommend that if you get a Security related exception to re-throw it.
Comment From: allurx
Thank you for your reply, my current practice is to re-throw spring-security related exceptions.
Comment From: aboutZZ
Same prolem here
Comment From: LeoSong121
Similar questions. Neither call AuthenticationEntryPoint, nor call global exception handler. But get: { "timestamp": 1589452582946, "status": 500, "error": "Internal Server Error", "message": "invalid token", "path": "/auth/xxx" }
Comment From: caiqichang
i got this problem if using .antMatcher() .
without any .antMatcher() , everything work well !
Comment From: rwinch
Closing. As mentioned before, there isn't anything we can do. Users may want to be handling the Security related exceptions.
Comment From: zhuzhiyun
Similar questions. Neither call AuthenticationEntryPoint, nor call global exception handler. But get: { "timestamp": 1589452582946, "status": 500, "error": "Internal Server Error", "message": "invalid token", "path": "/auth/xxx" }
I got this problem too,how to fix it?
Comment From: allurx
@zhuzhiyun Catch AccessDeniedException and AuthenticationException and throw them, AccessDeniedHandler and AuthenticationEntryPoint will work normally.see GlobalExceptionHandler
Comment From: aboutZZ
Similar questions. Neither call AuthenticationEntryPoint, nor call global exception handler. But get: { "timestamp": 1589452582946, "status": 500, "error": "Internal Server Error", "message": "invalid token", "path": "/auth/xxx" }
I got this problem too,how to fix it?
Hi, have you fixed this problem? Catch AuthenticationException then rethrow them, I'm still getting this:
{
"timestamp": "2021-04-12 15:52:07",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/api/xxxx/xxxx"
}
Comment From: allurx
@aboutZZ 我之前写的spring-security-demo,定义了一个全局异常捕获器捕获spring-security相关的异常,然后继续向上抛出就能进入到AccessDeniedHandler和AuthenticationEntryPoint中了,我怀疑你没有将这两个类配置进去,你看一下这个配置类WebSecurityConfig中的configure方法
Comment From: aboutZZ
@aboutZZ 我之前写的spring-security-demo,定义了一个全局异常捕获器捕获spring-security相关的异常,然后继续向上抛出就能进入到AccessDeniedHandler和AuthenticationEntryPoint中了,我怀疑你没有将这两个类配置进去,你看一下这个配置类WebSecurityConfig中的configure方法
全局异常捕获器捕获后再抛出
下面是配置类: 在自定义授权异常处理处配置了AuthenticationEntryPoint
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// We don't need CSRF for this example
httpSecurity.csrf().disable().logout().disable()
// Relax CSRF on the WebSocket due to needing direct access from apps
//.csrf().ignoringAntMatchers("/ws/**").and()
// dont authenticate this particular request
.authorizeRequests()
// OPTIONS请求全部放行
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/api/user/login").permitAll()
.antMatchers("/error").permitAll()
// all other requests need to be authenticated
.anyRequest().authenticated()
// make sure we use stateless session; session won't be used to
// store user's state.
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// Add a filter to validate the tokens with every request
.and().addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
// 自定义授权异常处理
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
// No cache
.and().headers().cacheControl()
;
写法应该没问题啊
Comment From: allurx
@aboutZZ 你在ExceptionTranslationFilter这个过滤器的doFilter方法中打断点看看呢,spring-security中的异常都会经过这个过滤器的,还有把异常堆栈贴一下,看看经过spring-security的哪几个过滤器了。
Comment From: aboutZZ
@aboutZZ 你在ExceptionTranslationFilter这个过滤器的doFilter方法中打断点看看呢,spring-security中的异常都会经过这个过滤器的,还有把异常堆栈贴一下,看看经过spring-security的哪几个过滤器了。
如下图, JwtRequestFilter是自定义的JWT认证过滤器
堆栈信息如下, 经过了以下几个过滤器
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- JwtRequestFilter
在经过JwtRequestFilter时抛出异常, 但是异常似乎被其中一个过滤器给处理了, ExceptionTranslationFilter中并未捕获到异常
debug发现被重定向到/error, 因此出现了那个默认的Json响应
堆栈信息如下:
Cause: java.sql.SQLSyntaxErrorException: Unknown column 'mobile2' in 'field list'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Unknown column 'mobile2' in 'field list'
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:239)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:88)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
at com.sun.proxy.$Proxy142.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:90)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at com.sun.proxy.$Proxy143.selectById(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205)
at com.sun.proxy.$Proxy144.selectById(Unknown Source)
at com.baomidou.mybatisplus.extension.service.IService.getById(IService.java:201)
at com.zbzl.service.impl.AppUserServiceImpl.lambda$getByIdUnSafely$1(AppUserServiceImpl.java:112)
at com.zbzl.service.impl.AppUserServiceImpl$$Lambda$1708/000000000000000000.get(Unknown Source)
at java.base/java.util.Optional.orElseGet(Optional.java:369)
at com.zbzl.service.impl.AppUserServiceImpl.getByIdUnSafely(AppUserServiceImpl.java:111)
at com.zbzl.service.impl.AppUserServiceImpl$$FastClassBySpringCGLIB$$8981be77.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)
at com.zbzl.service.impl.AppUserServiceImpl$$EnhancerBySpringCGLIB$$c53fb596.getByIdUnSafely(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205)
at com.sun.proxy.$Proxy109.getByIdUnSafely(Unknown Source)
at com.zbzl.config.security.JWTUserDetailService.loadUserByUsername(JWTUserDetailService.java:27)
at com.zbzl.config.security.JwtRequestFilter.doFilterInternal(JwtRequestFilter.java:87)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:836)
通过日志发现被重定向到/error:
2021-04-12 18:37:08.842 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /api/live/pull-stream/token?channel=devCOLLEGE_2356 at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2021-04-12 18:37:08.843 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /api/live/pull-stream/token?channel=devCOLLEGE_2356 at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2021-04-12 18:37:08.843 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /api/live/pull-stream/token?channel=devCOLLEGE_2356 at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2021-04-12 18:37:08.843 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /api/live/pull-stream/token?channel=devCOLLEGE_2356 at position 4 of 11 in additional filter chain; firing Filter: 'JwtRequestFilter'
2021-04-12 18:37:08.913 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@e7b35617
2021-04-12 18:37:08.913 DEBUG 14568 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 4 of 11 in additional filter chain; firing Filter: 'JwtRequestFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2021-04-12 18:37:08.915 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@4f09adb6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2021-04-12 18:37:08.916 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2021-04-12 18:37:08.916 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /error' doesn't match 'OPTIONS /**'
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/api/user/login'
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/error'
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /error?channel=devCOLLEGE_2356; Attributes: [permitAll]
2021-04-12 18:37:10.526 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@4f09adb6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2021-04-12 18:37:10.527 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@c15ad0f6, returned: 1
2021-04-12 18:37:10.527 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2021-04-12 18:37:10.527 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2021-04-12 18:37:10.527 DEBUG 14568 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy : /error?channel=devCOLLEGE_2356 reached end of additional filter chain; proceeding with original chain
2021-04-12 18:37:10.530 DEBUG 14568 --- [nio-8080-exec-6] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2021-04-12 18:37:10.530 DEBUG 14568 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Comment From: allurx
@aboutZZ 你把配置中的antMatchers("/error").permitAll()去掉再试试呢
Comment From: aboutZZ
@aboutZZ 你把配置中的
antMatchers("/error").permitAll()去掉再试试呢
Problem solved:
- 在认证过程中, 对可能异常的地方 (例如查询数据库) 捕获RuntimeException 然后抛出 InternalAuthenticationServiceException
final AppUserDetails userDetails;
try {
userDetails = (AppUserDetails) this.jwtUserDetailService.loadUserByUsername(username);
} catch (RuntimeException e) {
// not handle AuthenticationException
if (e instanceof AuthenticationException) throw e;
throw new InternalAuthenticationServiceException("Error while executing loadUserByUsername", e);
}
-
WebSecurityConfig中,自定义的JWT 认证过滤器放在AnonymousAuthenticationFilter之前addFilterBefore(jwtRequestFilter, AnonymousAuthenticationFilter.class) -
自定义控制器类, 实现
org.springframework.boot.web.servlet.error.ErrorController接口来自定义error page. Spring boot 2.3+中, 注意此处有坑, 尽管getErrorPath方法已被弃用, 你仍然要实现ErrorController接口, 否则不生效, 这应该是个BUG. 你的ErrorPath应当通过server.error.path配置.
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ErrorController implements org.springframework.boot.web.servlet.error.ErrorController {
@RequestMapping("/error")
public ResponseEntity<?> handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
int statusCode = (int) status;
final HttpStatus httpStatus = HttpStatus.valueOf(statusCode);
final String errMsg;
switch (httpStatus) {
case UNAUTHORIZED:
errMsg = "身份认证信息过期,请重新登录";
break;
case INTERNAL_SERVER_ERROR:
errMsg = "服务器内部错误";
break;
case FORBIDDEN:
errMsg = "无权限访问";
break;
... ... 省略代码
default:
errMsg = httpStatus.getReasonPhrase();
}
return ResponseEntity.status(httpStatus).body(new AppErrorResponse(errMsg));
}
@Override
public String getErrorPath() {
return "/error";
}
}
Comment From: allurx
@aboutZZ :wave::wave::wave: