spring security Saml2LogoutRequestFilter 源码
spring security Saml2LogoutRequestFilter 代码
文件路径:/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.web.authentication.logout;
import java.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidator;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequestValidatorParameters;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutValidatorResult;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.logout.CompositeLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.UriComponentsBuilder;
/**
* A filter for handling logout requests in the form of a <saml2:LogoutRequest> sent
* from the asserting party.
*
* @author Josh Cummings
* @since 5.6
* @see Saml2LogoutRequestValidator
*/
public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
private final Log logger = LogFactory.getLog(getClass());
private final Saml2LogoutRequestValidator logoutRequestValidator;
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
private final Saml2LogoutResponseResolver logoutResponseResolver;
private final LogoutHandler handler;
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher("/logout/saml2/slo");
/**
* Constructs a {@link Saml2LogoutResponseFilter} for accepting SAML 2.0 Logout
* Requests from the asserting party
* @param relyingPartyRegistrationResolver the strategy for resolving a
* {@link RelyingPartyRegistration}
* @param logoutRequestValidator the SAML 2.0 Logout Request authenticator
* @param logoutResponseResolver the strategy for creating a SAML 2.0 Logout Response
* @param handlers the actions that perform logout
*/
public Saml2LogoutRequestFilter(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver,
Saml2LogoutRequestValidator logoutRequestValidator, Saml2LogoutResponseResolver logoutResponseResolver,
LogoutHandler... handlers) {
this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
this.logoutRequestValidator = logoutRequestValidator;
this.logoutResponseResolver = logoutResponseResolver;
this.handler = new CompositeLogoutHandler(handlers);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
if (!this.logoutRequestMatcher.matches(request)) {
chain.doFilter(request, response);
return;
}
if (request.getParameter(Saml2ParameterNames.SAML_REQUEST) == null) {
chain.doFilter(request, response);
return;
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
RelyingPartyRegistration registration = this.relyingPartyRegistrationResolver.resolve(request,
getRegistrationId(authentication));
if (registration == null) {
this.logger
.trace("Did not process logout request since failed to find associated RelyingPartyRegistration");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (registration.getSingleLogoutServiceLocation() == null) {
this.logger.trace(
"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
Saml2MessageBinding saml2MessageBinding = Saml2MessageBindingUtils.resolveBinding(request);
if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) {
this.logger.trace("Did not process logout request since used incorrect binding");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
String serialized = request.getParameter(Saml2ParameterNames.SAML_REQUEST);
Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration)
.samlRequest(serialized).relayState(request.getParameter(Saml2ParameterNames.RELAY_STATE))
.binding(saml2MessageBinding).location(registration.getSingleLogoutServiceLocation())
.parameters((params) -> params.put(Saml2ParameterNames.SIG_ALG,
request.getParameter(Saml2ParameterNames.SIG_ALG)))
.parameters((params) -> params.put(Saml2ParameterNames.SIGNATURE,
request.getParameter(Saml2ParameterNames.SIGNATURE)))
.parametersQuery((params) -> request.getQueryString()).build();
Saml2LogoutRequestValidatorParameters parameters = new Saml2LogoutRequestValidatorParameters(logoutRequest,
registration, authentication);
Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters);
if (result.hasErrors()) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, result.getErrors().iterator().next().toString());
this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors()));
return;
}
this.handler.logout(request, response, authentication);
Saml2LogoutResponse logoutResponse = this.logoutResponseResolver.resolve(request, authentication);
if (logoutResponse == null) {
this.logger.trace("Returning 401 since no logout response generated");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
if (logoutResponse.getBinding() == Saml2MessageBinding.REDIRECT) {
doRedirect(request, response, logoutResponse);
}
else {
doPost(response, logoutResponse);
}
}
public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
Assert.notNull(logoutRequestMatcher, "logoutRequestMatcher cannot be null");
this.logoutRequestMatcher = logoutRequestMatcher;
}
private String getRegistrationId(Authentication authentication) {
if (authentication == null) {
return null;
}
Object principal = authentication.getPrincipal();
if (principal instanceof Saml2AuthenticatedPrincipal) {
return ((Saml2AuthenticatedPrincipal) principal).getRelyingPartyRegistrationId();
}
return null;
}
private void doRedirect(HttpServletRequest request, HttpServletResponse response,
Saml2LogoutResponse logoutResponse) throws IOException {
String location = logoutResponse.getResponseLocation();
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(location)
.query(logoutResponse.getParametersQuery());
this.redirectStrategy.sendRedirect(request, response, uriBuilder.build(true).toUriString());
}
private void doPost(HttpServletResponse response, Saml2LogoutResponse logoutResponse) throws IOException {
String location = logoutResponse.getResponseLocation();
String saml = logoutResponse.getSamlResponse();
String relayState = logoutResponse.getRelayState();
String html = createSamlPostRequestFormData(location, saml, relayState);
response.setContentType(MediaType.TEXT_HTML_VALUE);
response.getWriter().write(html);
}
private String createSamlPostRequestFormData(String location, String saml, String relayState) {
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html>\n");
html.append("<html>\n").append(" <head>\n");
html.append(" <meta http-equiv=\"Content-Security-Policy\" ")
.append("content=\"script-src 'sha256-ePniVEkSivX/c7XWBGafqh8tSpiRrKiqYeqbG7N1TOE='\">\n");
html.append(" <meta charset=\"utf-8\" />\n");
html.append(" </head>\n");
html.append(" <body onload=\"document.forms[0].submit()\">\n");
html.append(" <noscript>\n");
html.append(" <p>\n");
html.append(" <strong>Note:</strong> Since your browser does not support JavaScript,\n");
html.append(" you must press the Continue button once to proceed.\n");
html.append(" </p>\n");
html.append(" </noscript>\n");
html.append(" \n");
html.append(" <form action=\"");
html.append(location);
html.append("\" method=\"post\">\n");
html.append(" <div>\n");
html.append(" <input type=\"hidden\" name=\"SAMLResponse\" value=\"");
html.append(HtmlUtils.htmlEscape(saml));
html.append("\"/>\n");
if (StringUtils.hasText(relayState)) {
html.append(" <input type=\"hidden\" name=\"RelayState\" value=\"");
html.append(HtmlUtils.htmlEscape(relayState));
html.append("\"/>\n");
}
html.append(" </div>\n");
html.append(" <noscript>\n");
html.append(" <div>\n");
html.append(" <input type=\"submit\" value=\"Continue\"/>\n");
html.append(" </div>\n");
html.append(" </noscript>\n");
html.append(" </form>\n");
html.append(" \n");
html.append(" </body>\n");
html.append("</html>");
return html.toString();
}
}
相关信息
相关文章
spring security HttpSessionLogoutRequestRepository 源码
spring security OpenSamlLogoutRequestResolver 源码
spring security OpenSamlLogoutResponseResolver 源码
spring security OpenSamlSigningUtils 源码
spring security Saml2LogoutRequestRepository 源码
spring security Saml2LogoutRequestResolver 源码
spring security Saml2LogoutResponseFilter 源码
spring security Saml2LogoutResponseResolver 源码
spring security Saml2MessageBindingUtils 源码
spring security Saml2RelyingPartyInitiatedLogoutSuccessHandler 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦