All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.web.jaasapi.JaasApiIntegrationFilter Maven / Gradle / Ivy

There is a newer version: 6.3.1
Show newest version
/*
 * Copyright 2010-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.web.jaasapi;

import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;

/**
 * 

* A Filter which attempts to obtain a JAAS Subject and continue * the FilterChain running as that Subject. *

*

* By using this Filter in conjunction with Spring's * JaasAuthenticationProvider both Spring's SecurityContext and * a JAAS Subject can be populated simultaneously. This is useful when * integrating with code that requires a JAAS Subject to be populated. *

* * @author Rob Winch * @see #doFilter(ServletRequest, ServletResponse, FilterChain) * @see #obtainSubject(ServletRequest) */ public class JaasApiIntegrationFilter extends GenericFilterBean { private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder .getContextHolderStrategy(); private boolean createEmptySubject; /** *

* Attempts to obtain and run as a JAAS Subject using * {@link #obtainSubject(ServletRequest)}. *

* *

* If the Subject is null and createEmptySubject is * true, an empty, writeable Subject is used. This allows * for the Subject to be populated at the time of login. If the * Subject is null, the FilterChain continues * with no additional processing. If the Subject is not null * , the FilterChain is ran with * {@link Subject#doAs(Subject, PrivilegedExceptionAction)} in conjunction with the * Subject obtained. *

*/ @Override public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { Subject subject = obtainSubject(request); if (subject == null && this.createEmptySubject) { this.logger.debug("Subject returned was null and createEmptySubject is true; " + "creating new empty subject to run as."); subject = new Subject(); } if (subject == null) { this.logger.debug("Subject is null continue running with no Subject."); chain.doFilter(request, response); return; } this.logger.debug(LogMessage.format("Running as Subject %s", subject)); try { Subject.doAs(subject, (PrivilegedExceptionAction) () -> { chain.doFilter(request, response); return null; }); } catch (PrivilegedActionException ex) { throw new ServletException(ex.getMessage(), ex); } } /** *

* Obtains the Subject to run as or null if no * Subject is available. *

*

* The default implementation attempts to obtain the Subject from the * SecurityContext's Authentication. If it is of type * JaasAuthenticationToken and is authenticated, the Subject * is returned from it. Otherwise, null is returned. *

* @param request the current ServletRequest * @return the Subject to run as or null if no Subject is * available. */ protected Subject obtainSubject(ServletRequest request) { Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication(); this.logger.debug(LogMessage.format("Attempting to obtainSubject using authentication : %s", authentication)); if (authentication == null) { return null; } if (!authentication.isAuthenticated()) { return null; } if (!(authentication instanceof JaasAuthenticationToken token)) { return null; } LoginContext loginContext = token.getLoginContext(); if (loginContext == null) { return null; } return loginContext.getSubject(); } /** * Sets createEmptySubject. If the value is true, and * {@link #obtainSubject(ServletRequest)} returns null, an empty, * writeable Subject is created instead. Otherwise no * Subject is used. The default is false. * @param createEmptySubject the new value */ public final void setCreateEmptySubject(boolean createEmptySubject) { this.createEmptySubject = createEmptySubject; } /** * Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use * the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}. * * @since 5.8 */ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) { Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null"); this.securityContextHolderStrategy = securityContextHolderStrategy; } }