推荐设计网站,被执行人信息查询,韩国 网站 域名,iis网站管理助手概述
与Spring、Spring MVC、Spring Boot一样#xff0c;Spring Security里也有很多Handler接口、可以分为两大类#xff0c;一类是普通的XxxHandler#xff08;见名知意#xff09;#xff0c;另一类是对应的ServerXxxHandler#xff08;RequestRejectedHandler除外Spring Security里也有很多Handler接口、可以分为两大类一类是普通的XxxHandler见名知意另一类是对应的ServerXxxHandlerRequestRejectedHandler除外。
以AuthenticationSuccessHandler为例Spring Security中用于处理认证成功事件的接口。通常与基于Servlet API的应用程序一起使用如Spring MVC应用程序。当用户成功认证后接口的实现类负责处理接下来的操作如重定向到其他页面、生成认证成功的日志等。主要实现类是SavedRequestAwareAuthenticationSuccessHandler它会将用户重定向到之前被拦截的原始请求地址。
而对应的ServerAuthenticationSuccessHandler在Spring Security 5引入的新接口用于处理WebFlux中的认证成功事件。WebFlux是Spring Framework 5中引入的反应式编程模型用于构建响应式的、非阻塞的、事件驱动的应用程序。该接口的实现类负责发送响应给客户端例如返回 JSON 格式的认证成功消息。
Spring Security里定义的Handler接口具体如下
AuthenticationSuccessHandlerAuthenticationFailureHandlerLogoutHandlerLogoutSuccessHandlerAccessDeniedHandlerCsrfTokenRequestHandlerRequestRejectedHandlerServerAuthenticationSuccessHandlerServerAuthenticationFailureHandlerServerLogoutHandlerServerLogoutSuccessHandlerServerAccessDeniedHandlerServerCsrfTokenRequestHandler
AuthenticationSuccessHandler
AuthenticationSuccessHandler接口用来设置验证成功后的处理动作源码如下
public interface AuthenticationSuccessHandler {default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {this.onAuthenticationSuccess(request, response, authentication);chain.doFilter(request, response);}void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}有两个同名onAuthenticationSuccess方法default方法用于处理特定的认证请求AuthenticationFilter非default方法则用来处理登录成功的具体事项。目前有3个实现类
ForwardAuthenticationSuccessHandler实现服务端跳转SimpleUrlAuthenticationSuccessHandler同时继承AbstractAuthenticationTargetUrlRequestHandler通过其中的handle方法实现请求重定向SavedRequestAwareAuthenticationSuccessHandler继承自SimpleUrlAuthenticationSuccessHandler在其基础上增加请求缓存的功能可以记录之前请求的地址进而在登录成功后重定向到一开始访问的地址。 开发者也可以配置自己的SavedRequestAwareAuthenticationSuccessHandler方法如下
SavedRequestAwareAuthenticationSuccessHandler successHandler() {SavedRequestAwareAuthenticationSuccessHandler handler new SavedRequestAwareAuthenticationSuccessHandler;handler.setDefaultTargetUrl(/index);handler.setTargetUrlParameter(target);return handler;
}ForwardAuthenticationSuccessHandler的onAuthenticationSuccess方法就一行request.getRequestDispatcher(this.forwardUrl).forward(request, response);即调用getRequestDispatcher方法进行服务端转发
AuthenticationFailureHandler
AuthenticationFailureHandler接口用来设置用户验证失败后的处理动作源码如下
public interface AuthenticationFailureHandler {void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException;
}实现类有
SimpleUrlAuthenticationFailureHandler默认如果指定failureUrl则跳转到该URL未指定则返回401错误代码。也可以通过配置forwardToDestination属性将重定向改为服务器端跳转ForwardAuthenticationFailureHandler不管报哪种AuthenticationException总是重定向到指定的URLDelegatingAuthenticationFailureHandler代理类可根据不同的AuthenticationException类型设置不同的HandlersExceptionMappingAuthenticationFailureHandler可以根据不同的AuthenticationException类型设置不同的跳转URLAuthenticationEntryPointFailureHandler可通过AuthenticationEntryPoint来处理登录异常
类继承图 DelegatingAuthenticationFailureHandler处理方法handle如下
// 维护一个mapkey是具体的异常类型value是特定的Handler
private final LinkedHashMapClass? extends AuthenticationException, AuthenticationFailureHandler handlers;public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {for (Map.EntryClass? extends AuthenticationException, AuthenticationFailureHandler entry : this.handlers.entrySet()) {Class? extends AuthenticationException handlerMappedExceptionClass entry.getKey();if (handlerMappedExceptionClass.isAssignableFrom(exception.getClass())) {AuthenticationFailureHandler handler entry.getValue();handler.onAuthenticationFailure(request, response, exception);return;}}this.defaultHandler.onAuthenticationFailure(request, response, exception);
}值得注意的是Delegating代理的意思。此实现类里维护一个Map此Map集合支持通过构造函数的入参这种方式来实例化Handler类然后在核心方法里对Map里的key进行遍历与方法入参里的exception对比比对成功则加以处理。最后使用默认的Handler加以处理。这种思想在下面的几个Handler里几乎都是如此。不同的是Map的key不一样核心方法名不一样一般都命名为handle()对比项不一样有的是对比request。不再赘述。
LogoutHandler
LogoutHandler接口设置logout过程中必须处理动作logout后的重定向建议使用LogoutSuccessHandler源码如下
public interface LogoutHandler {void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
}有如下几个实现类
AbstractRememberMeServicesCompositeLogoutHandlerCookieClearingLogoutHandler清除CookieCsrfLogoutHandler通过CsrfTokenRepository清除CsrfTokenHeaderWriterLogoutHandlerLogoutSuccessEventPublishingLogoutHandler同时实现ApplicationEventPublisherAware发布一个事件通知OidcBackChannelLogoutHandlerPersistentTokenBasedRememberMeServicesSecurityContextLogoutHandlerSpringSessionRememberMeServicesTokenBasedRememberMeServices
CompositeLogoutHandler接口源码如下
private final ListLogoutHandler logoutHandlers;
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {for (LogoutHandler handler : this.logoutHandlers) {handler.logout(request, response, authentication);}
}分析下来与Delegating比较类似不同的是维护一个ListxxxHandler构造函数同样支持传入指定的ListxxxHandler然后在具体的handle方法里此处是logout方法for循环遍历list分别使用具体的Handler来一一处理。类似地下文也有几个CompositeXxxHandler思想与此非常相似。
LogoutSuccessHandler
LogoutSuccessHandler接口设置logout完成后需要处理动作在LogoutHandler后被执行LogoutHandler完成必要的动作该过程不应该抛异常LogoutSuccessHandler定位是处理后续更多的步骤如重定向等源码如下
public interface LogoutSuccessHandler {void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}有如下几个实现类
SimpleUrlLogoutSuccessHandler和上面的AuthenticationSuccessHandler非常类似继承AbstractAuthenticationTargetUrlRequestHandler通过其中的handle方法实现请求重定向DelegatingLogoutSuccessHandlerHttpStatusReturningLogoutSuccessHandler设置状态码200ForwardLogoutSuccessHandler通过构造函数传入的目标URL即targetUrl参数实现转发。
AccessDeniedHandler
AccessDeniedHandler接口用来设置访问拒绝后的处理动作源码如下
public interface AccessDeniedHandler {void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException;
}有如下几个实现类
NoOpAccessDeniedHandler熟悉的NoOp。空实现不做任何处理AccessDeniedHandlerImpl设置403错误码然后转发请求让下一个Handler来处理DelegatingAccessDeniedHandlerCompositeAccessDeniedHandler组合模式for循环遍历各个Handler实现类依次调用其handle方法进行处理InvalidSessionAccessDeniedHandler清除缓存ObservationMarkingAccessDeniedHandlerRequestMatcherDelegatingAccessDeniedHandler代理模式维护一个map映射集合。根据具体的RequestMatcher匹配对应的Handler实现类匹配成功则加以处理。最后使用defaultHandler加以处理。OAuth2AccessDeniedHandlerspring-security-oauth2包里面的实现类同时继承AbstractOAuth2SecurityExceptionHandler类直接调用父类里的handle方法。
CsrfTokenRequestHandler
CSRFCross-Site Request Forgery跨站请求伪造是一种攻击技术攻击者利用用户在已登录的状态下发起的请求来执行非法操作。
CsrfTokenRequestHandler是Spring Security种用于处理CSRF攻击的处理程序。具体来说浏览器向服务器发送请求时服务器会在响应中返回一个CSRF令牌。在后续的请求中浏览器将该令牌包含在请求中服务器会验证该令牌的有效性从而防止CSRF攻击。
函数式接口源码如下
FunctionalInterface
public interface CsrfTokenRequestHandler extends CsrfTokenRequestResolver {void handle(HttpServletRequest request, HttpServletResponse response, SupplierCsrfToken csrfToken);default String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {Assert.notNull(request, request cannot be null);Assert.notNull(csrfToken, csrfToken cannot be null);String actualToken request.getHeader(csrfToken.getHeaderName());if (actualToken null) {actualToken request.getParameter(csrfToken.getParameterName());}return actualToken;}
}实现类包括
CsrfTokenRequestAttributeHandlerXorCsrfTokenRequestAttributeHandler执行异或xor运算
RequestRejectedHandler
位于org.springframework.security.web.firewall包路径下可知与防火墙策略相关用于处理请求被拒绝的场景。当请求因为安全策略而被拒绝时其实现类负责向用户发送相应的错误信息或执行其他定制的行为。
源码如下
public interface RequestRejectedHandler {void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException requestRejectedException) throws IOException, ServletException;
}实现类包括
DefaultRequestRejectedHandler不做处理抛出异常HttpStatusRequestRejectedHandler通过response.sendError(this.httpError);发送错误响应状态码默认400支持构造方法传参ObservationMarkingRequestRejectedHandlerCompositeRequestRejectedHandler组合模式for循环遍历列表里的所有实现类一一加以处理。
ObservationMarkingRequestRejectedHandler的handle方法如下
private final ObservationRegistry registry;public void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException exception) throws IOException, ServletException {Observation observation this.registry.getCurrentObservation();if (observation ! null) {observation.error(exception);}
}有点复杂。
ServerAuthenticationSuccessHandler
与AuthenticationSuccessHandler接口定义几乎一致不同的是只有一个非default方法
HttpServletRequest request, HttpServletResponse response两个参数变成一个参数WebFilterExchange webFilterExchange返回参数void也变成响应式的MonoVoid
public interface ServerAuthenticationSuccessHandler {MonoVoid onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication);
}实现类
DelegatingServerAuthenticationSuccessHandlerRedirectServerAuthenticationSuccessHandlerWebFilterChainServerAuthenticationSuccessHandler
ServerAuthenticationFailureHandler
同上面的ServerAuthenticationSuccessHandler非常类似。实现类
RedirectServerAuthenticationFailureHandlerServerAuthenticationEntryPointFailureHandler
ServerLogoutHandler
与上面的非常相似实现类
CsrfServerLogoutHandlerDelegatingServerLogoutHandlerHeaderWriterServerLogoutHandlerOidcBackChannelServerLogoutHandlerSecurityContextServerLogoutHandlerWebSessionServerLogoutHandler将WebFilterExchange里保存的WebSession做失效处理exchange.getExchange().getSession().flatMap(WebSession::invalidate);
ServerLogoutSuccessHandler
源码比较简单实现类
HttpStatusReturningServerLogoutSuccessHandlerRedirectServerLogoutSuccessHandler
ServerAccessDeniedHandler
ServerAccessDeniedHandler接口源码如下
public interface ServerAccessDeniedHandler {MonoVoid handle(ServerWebExchange exchange, AccessDeniedException denied);
}实现类
HttpStatusServerAccessDeniedHandlerServerWebExchangeDelegatingServerAccessDeniedHandler
ServerCsrfTokenRequestHandler
接口定义如下
FunctionalInterface
public interface ServerCsrfTokenRequestHandler extends ServerCsrfTokenRequestResolver {void handle(ServerWebExchange exchange, MonoCsrfToken csrfToken);default MonoString resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {Assert.notNull(exchange, exchange cannot be null);Assert.notNull(csrfToken, csrfToken cannot be null);return exchange.getFormData().flatMap((data) - {return Mono.justOrEmpty((String)data.getFirst(csrfToken.getParameterName()));}).switchIfEmpty(Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst(csrfToken.getHeaderName())));}
}参考