您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“SpringBoot Security如何自定義異常處理”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“SpringBoot Security如何自定義異常處理”這篇文章吧。
原異常
{ "error": "access_denied", "error_description": "不允許訪問" }
現(xiàn)異常
{ "success": false, "error": "access_denied", "status": 403, "message": "不允許訪問", "path": "/user/get1", "timestamp": 1592378892768 }
實(shí)現(xiàn)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) { // access_denied 方面異常 OAuth3AccessDeniedHandler oAuth3AccessDeniedHandler = new OAuth3AccessDeniedHandler(); oAuth3AccessDeniedHandler.setExceptionTranslator(new CustomWebResponseExceptionTranslator()); resources.accessDeniedHandler(oAuth3AccessDeniedHandler); } }
原異常
{ "error": "invalid_token", "error_description": "Invalid access token: 4eb58ecf-e66de-4155-9477-64a1c9805cc8" }
現(xiàn)異常
{ "success": false, "error": "invalid_token", "status": 401, "message": "Invalid access token: 8cd45925dbf6-4502-bd13-8101bc6e1d4b", "path": "/user/get1", "timestamp": 1592378949452 }
實(shí)現(xiàn)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) { // Invalid access token 方面異常 OAuth3AuthenticationEntryPoint authenticationEntryPoint = new OAuth3AuthenticationEntryPoint(); authenticationEntryPoint.setExceptionTranslator(new CustomWebResponseExceptionTranslator()); resources.authenticationEntryPoint(authenticationEntryPoint); } }
原異常
{ "error": "invalid_grant", "error_description": "用戶名或密碼錯(cuò)誤" }
現(xiàn)異常
{ "success": false, "error": "invalid_grant", "status": 400, "message": "用戶名或密碼錯(cuò)誤", "path": "/oauth/token", "timestamp": 1592384576019 }
實(shí)現(xiàn)
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints.userDetailsService(detailsService) .tokenStore(memoryTokenStore()) .exceptionTranslator(new CustomWebResponseExceptionTranslator()) .authenticationManager(authenticationManager) //接收GET和POST .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); } }
@Getter @JsonSerialize(using = CustomOauthExceptionSerializer.class) public class CustomOauthException extends OAuth3Exception { private String oAuth3ErrorCode; private int httpErrorCode; public CustomOauthException(String msg, String oAuth3ErrorCode, int httpErrorCode) { super(msg); this.oAuth3ErrorCode = oAuth3ErrorCode; this.httpErrorCode = httpErrorCode; } }
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> { private static final long serialVersionUID = 2652127645704345563L; public CustomOauthExceptionSerializer() { super(CustomOauthException.class); } @Override public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); gen.writeObjectField("success",false); gen.writeObjectField("error",value.getOAuth3ErrorCode()); gen.writeObjectField("status", value.getHttpErrorCode()); gen.writeObjectField("message", value.getMessage()); gen.writeObjectField("path", request.getServletPath()); gen.writeObjectField("timestamp", (new Date()).getTime()); if (value.getAdditionalInformation()!=null) { for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) { String key = entry.getKey(); String add = entry.getValue(); gen.writeObjectField(key, add); } } gen.writeEndObject(); } }
public class CustomWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator { @Override public ResponseEntity<OAuth3Exception> translate(Exception e) throws Exception { ResponseEntity<OAuth3Exception> translate = super.translate(e); OAuth3Exception body = translate.getBody(); CustomOauthException customOauthException = new CustomOauthException(body.getMessage(),body.getOAuth3ErrorCode(),body.getHttpErrorCode()); ResponseEntity<OAuth3Exception> response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode()); return response; } }
{ "error": "invalid_client", "error_description": "Bad client credentials" }
如果client_secret錯(cuò)誤依然還是報(bào)錯(cuò),如上內(nèi)容,針對(duì)這個(gè)異常需要在如下方法中的addTokenEndpointAuthenticationFilter添加過濾器處理
@Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) { oauthServer // 開啟/oauth/token_key驗(yàn)證端口無權(quán)限訪問 .tokenKeyAccess("permitAll()") // 開啟/oauth/check_token驗(yàn)證端口認(rèn)證權(quán)限訪問 .checkTokenAccess("isAuthenticated()") .addTokenEndpointAuthenticationFilter(null) .allowFormAuthenticationForClients(); }
此處的異常信息設(shè)置的話,其中還是有坑的,比如你想自定義token過期信息,無效token這些,如果按照SpringSecurity的設(shè)置是不會(huì)生效的,需要加到資源的配置中。
如果只是SpringSecurity的話,只需要實(shí)現(xiàn)AccessDeniedHandler和AuthenticationEntryPoint這2個(gè)接口就可以了。他們都是在ExceptionTranslationFilter中生效的。
AuthenticationEntryPoint
用來解決匿名用戶訪問無權(quán)限資源時(shí)的異常
ruAccessDeineHandler
用來解決認(rèn)證過的用戶訪問無權(quán)限資源時(shí)的異常
如果你想自定義token過期的話,需要實(shí)現(xiàn)AuthenticationEntryPoint這個(gè)接口,因?yàn)閠oken過期了,訪問的話也算是匿名訪問。
但是SpringSecurity的過濾器鏈中其實(shí)是有順序的,校驗(yàn)token的OAuth3AuthenticationProcessingFilter在它前面,導(dǎo)致一直沒有辦法生效,所有需要添加到資源的配置上,demo如下:
/** * @author WGR * @create 2021/8/23 -- 16:52 */ @Component public class SimpleAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws ServletException { Throwable cause = authException.getCause(); try { if (cause instanceof InvalidTokenException) { Map map = new HashMap(); map.put("error", "無效token"); map.put("message", authException.getMessage()); map.put("path", request.getServletPath()); map.put("timestamp", String.valueOf(new Date().getTime())); response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); try { ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(response.getOutputStream(), map); } catch (Exception e) { throw new ServletException(); } } } catch (Exception e) { e.printStackTrace(); } } }
則可以生效,返回信息具體如下:
如果想設(shè)置沒有權(quán)限的自定義異常信息的話:
/** * @author WGR * @create 2021/8/23 -- 17:09 */ @Component public class SimpleAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { Map map = new HashMap(); map.put("message", "無權(quán)操作"); map.put("path", request.getServletPath()); map.put("timestamp", String.valueOf(new Date().getTime())); response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_FORBIDDEN); try { ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(response.getOutputStream(), map); } catch (Exception e) { throw new ServletException(); } } }
把它設(shè)置到springsecurity中,添加進(jìn)去就可以了,如果不是想要捕獲token過期的話,就直接添加進(jìn)去也可以
以上是“SpringBoot Security如何自定義異常處理”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。