private RootBeanDefinition createEmbeddedServer(Element element,
			ParserContext parserContext) {
		Object source = parserContext.extractSource(element);

		String suffix = element.getAttribute(ATT_ROOT_SUFFIX);

		if (!StringUtils.hasText(suffix)) {
			suffix = OPT_DEFAULT_ROOT_SUFFIX;
		}

		String port = element.getAttribute(ATT_PORT);

		if (!StringUtils.hasText(port)) {
			port = getDefaultPort();
			if (logger.isDebugEnabled()) {
				logger.debug("Using default port of " + port);
			}
		}

		String url = "ldap://127.0.0.1:" + port + "/" + suffix;

		BeanDefinitionBuilder contextSource = BeanDefinitionBuilder
				.rootBeanDefinition(CONTEXT_SOURCE_CLASS);
		contextSource.addConstructorArgValue(url);
		contextSource.addPropertyValue("userDn", "uid=admin,ou=system");
		contextSource.addPropertyValue("password", "secret");

		RootBeanDefinition apacheContainer = new RootBeanDefinition(
				"org.springframework.security.ldap.server.ApacheDSContainer", null, null);
		apacheContainer.setSource(source);
		apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix);

		String ldifs = element.getAttribute(ATT_LDIF_FILE);
		if (!StringUtils.hasText(ldifs)) {
			ldifs = OPT_DEFAULT_LDIF_FILE;
		}

		apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
		apacheContainer.getPropertyValues().addPropertyValue("port", port);

		logger.info("Embedded LDAP server bean definition created for URL: " + url);

		if (parserContext.getRegistry()
				.containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)) {
			parserContext.getReaderContext().error(
					"Only one embedded server bean is allowed per application context",
					element);
		}

		parserContext.getRegistry().registerBeanDefinition(BeanIds.EMBEDDED_APACHE_DS,
				apacheContainer);

		return (RootBeanDefinition) contextSource.getBeanDefinition();
	}

Will be called if no url attribute is supplied.

Registers beans to create an embedded apache directory server.

@return the BeanDefinition for the ContextSource for the embedded server.

@see ApacheDSContainer

Will be called if no url attribute is supplied .


private void createServletApiFilter(BeanReference authenticationManager) {
		final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
		final String DEF_SERVLET_API_PROVISION = "true";

		String provideServletApi = httpElt.getAttribute(ATT_SERVLET_API_PROVISION);
		if (!StringUtils.hasText(provideServletApi)) {
			provideServletApi = DEF_SERVLET_API_PROVISION;
		}

		if ("true".equals(provideServletApi)) {
			servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, SecurityContextHolderAwareRequestFilterBeanFactory.class);
			servApiFilter.getPropertyValues().add("authenticationManager",
					authenticationManager);
		}
	}

Adds the servlet-api integration filter if required

Adds the servlet - api integration filter if required


private void createJaasApiFilter() {
		final String ATT_JAAS_API_PROVISION = "jaas-api-provision";
		final String DEF_JAAS_API_PROVISION = "false";

		String provideJaasApi = httpElt.getAttribute(ATT_JAAS_API_PROVISION);
		if (!StringUtils.hasText(provideJaasApi)) {
			provideJaasApi = DEF_JAAS_API_PROVISION;
		}

		if ("true".equals(provideJaasApi)) {
			jaasApiFilter = new RootBeanDefinition(JaasApiIntegrationFilter.class);
		}
	}

private void createJaasApiFilter ( ) { final String ATT_JAAS_API_PROVISION = "jaas-api-provision" ; final String DEF_JAAS_API_PROVISION = "false" ; String provideJaasApi = httpElt . getAttribute ( ATT_JAAS_API_PROVISION ) ; if ( ! StringUtils . hasText ( provideJaasApi ) ) { provideJaasApi = DEF_JAAS_API_PROVISION ; } if ( "true" . equals ( provideJaasApi ) ) { jaasApiFilter = new RootBeanDefinition ( JaasApiIntegrationFilter . class ) ; } }

Adds the jaas-api integration filter if required

Adds the jaas - api integration filter if required


private static TypeResolverBuilder<? extends TypeResolverBuilder> createWhitelistedDefaultTyping() {
		TypeResolverBuilder<? extends TypeResolverBuilder>  result = new WhitelistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
		result = result.init(JsonTypeInfo.Id.CLASS, null);
		result = result.inclusion(JsonTypeInfo.As.PROPERTY);
		return result;
	}

private static TypeResolverBuilder < ? extends TypeResolverBuilder > createWhitelistedDefaultTyping ( ) { TypeResolverBuilder < ? extends TypeResolverBuilder > result = new WhitelistTypeResolverBuilder ( ObjectMapper . DefaultTyping . NON_FINAL ) ; result = result . init ( JsonTypeInfo . Id . CLASS , null ) ; result = result . inclusion ( JsonTypeInfo . As . PROPERTY ) ; return result ; }

Creates a TypeResolverBuilder that performs whitelisting.
@return a TypeResolverBuilder that performs whitelisting.

Creates a TypeResolverBuilder that performs whitelisting .


private void insertSpringSecurityFilterChain(ServletContext servletContext) {
		String filterName = DEFAULT_FILTER_NAME;
		DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(
				filterName);
		String contextAttribute = getWebApplicationContextAttribute();
		if (contextAttribute != null) {
			springSecurityFilterChain.setContextAttribute(contextAttribute);
		}
		registerFilter(servletContext, true, filterName, springSecurityFilterChain);
	}

private void insertSpringSecurityFilterChain ( ServletContext servletContext ) { String filterName = DEFAULT_FILTER_NAME ; DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy ( filterName ) ; String contextAttribute = getWebApplicationContextAttribute ( ) ; if ( contextAttribute != null ) { springSecurityFilterChain . setContextAttribute ( contextAttribute ) ; } registerFilter ( servletContext , true , filterName , springSecurityFilterChain ) ; }

Registers the springSecurityFilterChain
@param servletContext the {@link ServletContext}


public PersistentRememberMeToken getTokenForSeries(String seriesId) {
		try {
			return getJdbcTemplate().queryForObject(tokensBySeriesSql,
					new RowMapper<PersistentRememberMeToken>() {
						public PersistentRememberMeToken mapRow(ResultSet rs, int rowNum)
								throws SQLException {
							return new PersistentRememberMeToken(rs.getString(1), rs
									.getString(2), rs.getString(3), rs.getTimestamp(4));
						}
					}, seriesId);
		}
		catch (EmptyResultDataAccessException zeroResults) {
			if (logger.isDebugEnabled()) {
				logger.debug("Querying token for series '" + seriesId
						+ "' returned no results.", zeroResults);
			}
		}
		catch (IncorrectResultSizeDataAccessException moreThanOne) {
			logger.error("Querying token for series '" + seriesId
					+ "' returned more than one value. Series" + " should be unique");
		}
		catch (DataAccessException e) {
			logger.error("Failed to load token for series " + seriesId, e);
		}

		return null;
	}

Loads the token data for the supplied series identifier.

If an error occurs, it will be reported and null will be returned (since the result
should just be a failed persistent login).

@param seriesId
@return the token matching the series, or null if no match found or an exception
occurred.

Loads the token data for the supplied series identifier .


public List<GrantedAuthority> getGrantedAuthorities(Collection<String> attributes) {
		List<GrantedAuthority> result = new ArrayList<>(attributes.size());
		for (String attribute : attributes) {
			result.add(getGrantedAuthority(attribute));
		}
		return result;
	}

public List < GrantedAuthority > getGrantedAuthorities ( Collection < String > attributes ) { List < GrantedAuthority > result = new ArrayList <> ( attributes . size ( ) ) ; for ( String attribute : attributes ) { result . add ( getGrantedAuthority ( attribute ) ) ; } return result ; }

Map the given list of string attributes one-to-one to Spring Security
GrantedAuthorities.

Map the given list of string attributes one - to - one to Spring Security GrantedAuthorities .


public static Cipher newCipher(String algorithm) {
		try {
			return Cipher.getInstance(algorithm);
		}
		catch (NoSuchAlgorithmException e) {
			throw new IllegalArgumentException("Not a valid encryption algorithm", e);
		}
		catch (NoSuchPaddingException e) {
			throw new IllegalStateException("Should not happen", e);
		}
	}

public
static
Cipher
newCipher
(
String
algorithm
)
{
try
{
return
Cipher
.
getInstance
(
algorithm
)
;
}
catch
(
NoSuchAlgorithmException
e
)
{
throw
new
IllegalArgumentException
(
"Not a valid encryption algorithm"
,
e
)
;
}
catch
(
NoSuchPaddingException
e
)
{
throw
new
IllegalStateException
(
"Should not happen"
,
e
)
;
}
}


@Override
	public void afterPropertiesSet() {
		try {
			super.afterPropertiesSet();
		}
		catch (ServletException e) {
			// convert to RuntimeException for passivity on afterPropertiesSet signature
			throw new RuntimeException(e);
		}
		Assert.notNull(authenticationManager, "An AuthenticationManager must be set");
	}

Check whether all required properties have been set.

Check whether all required properties have been set .


public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		if (logger.isDebugEnabled()) {
			logger.debug("Checking secure context token: "
					+ SecurityContextHolder.getContext().getAuthentication());
		}

		if (requiresAuthentication((HttpServletRequest) request)) {
			doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
		}

		chain.doFilter(request, response);
	}

public
void
doFilter
(
ServletRequest
request
,
ServletResponse
response
,
FilterChain
chain
)
throws
IOException
,
ServletException
{
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"Checking secure context token: "
+
SecurityContextHolder
.
getContext
(
)
.
getAuthentication
(
)
)
;
}
if
(
requiresAuthentication
(
(
HttpServletRequest
)
request
)
)
{
doAuthenticate
(
(
HttpServletRequest
)
request
,
(
HttpServletResponse
)
response
)
;
}
chain
.
doFilter
(
request
,
response
)
;
}

Try to authenticate a pre-authenticated user with Spring Security if the user has
not yet been authenticated.

Try to authenticate a pre - authenticated user with Spring Security if the user has not yet been authenticated .


protected boolean principalChanged(HttpServletRequest request, Authentication currentAuthentication) {

		Object principal = getPreAuthenticatedPrincipal(request);

		if ((principal instanceof String) && currentAuthentication.getName().equals(principal)) {
			return false;
		}

		if (principal != null && principal.equals(currentAuthentication.getPrincipal())) {
			return false;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Pre-authenticated principal has changed to " + principal + " and will be reauthenticated");
		}
		return true;
	}

Determines if the current principal has changed. The default implementation tries

If the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is a String, the {@link Authentication#getName()} is compared against the pre authenticated principal

Otherwise, the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is compared against the {@link Authentication#getPrincipal()}

Subclasses can override this method to determine when a principal has changed.

@param request
@param currentAuthentication
@return true if the principal has changed, else false

Determines if the current principal has changed . The default implementation tries


private void doAuthenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		Authentication authResult;

		Object principal = getPreAuthenticatedPrincipal(request);
		Object credentials = getPreAuthenticatedCredentials(request);

		if (principal == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("No pre-authenticated principal found in request");
			}

			return;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("preAuthenticatedPrincipal = " + principal
					+ ", trying to authenticate");
		}

		try {
			PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(
					principal, credentials);
			authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
			authResult = authenticationManager.authenticate(authRequest);
			successfulAuthentication(request, response, authResult);
		}
		catch (AuthenticationException failed) {
			unsuccessfulAuthentication(request, response, failed);

			if (!continueFilterChainOnUnsuccessfulAuthentication) {
				throw failed;
			}
		}
	}

Do the actual authentication for a pre-authenticated user.

Do the actual authentication for a pre - authenticated user .


private void checkContentLength(long contentLengthToWrite) {
		this.contentWritten += contentLengthToWrite;
		boolean isBodyFullyWritten = this.contentLength > 0
				&& this.contentWritten >= this.contentLength;
		int bufferSize = getBufferSize();
		boolean requiresFlush = bufferSize > 0 && this.contentWritten >= bufferSize;
		if (isBodyFullyWritten || requiresFlush) {
			doOnResponseCommitted();
		}
	}

private void checkContentLength ( long contentLengthToWrite ) { this . contentWritten += contentLengthToWrite ; boolean isBodyFullyWritten = this . contentLength > 0 && this . contentWritten >= this . contentLength ; int bufferSize = getBufferSize ( ) ; boolean requiresFlush = bufferSize > 0 && this . contentWritten >= bufferSize ; if ( isBodyFullyWritten || requiresFlush ) { doOnResponseCommitted ( ) ; } }

Adds the contentLengthToWrite to the total contentWritten size and checks to see if
the response should be written.

@param contentLengthToWrite the size of the content that is about to be written.

Adds the contentLengthToWrite to the total contentWritten size and checks to see if the response should be written .


public Set<GrantedAuthority> mapAuthorities(
			Collection<? extends GrantedAuthority> authorities) {
		HashSet<GrantedAuthority> mapped = new HashSet<>(
				authorities.size());
		for (GrantedAuthority authority : authorities) {
			mapped.add(mapAuthority(authority.getAuthority()));
		}

		if (defaultAuthority != null) {
			mapped.add(defaultAuthority);
		}

		return mapped;
	}

public Set < GrantedAuthority > mapAuthorities ( Collection < ? extends GrantedAuthority > authorities ) { HashSet < GrantedAuthority > mapped = new HashSet <> ( authorities . size ( ) ) ; for ( GrantedAuthority authority : authorities ) { mapped . add ( mapAuthority ( authority . getAuthority ( ) ) ) ; } if ( defaultAuthority != null ) { mapped . add ( defaultAuthority ) ; } return mapped ; }

Creates a mapping of the supplied authorities based on the case-conversion and
prefix settings. The mapping will be one-to-one unless duplicates are produced
during the conversion. If a default authority has been set, this will also be
assigned to each mapping.

@param authorities the original authorities

@return the converted set of authorities

Creates a mapping of the supplied authorities based on the case - conversion and prefix settings . The mapping will be one - to - one unless duplicates are produced during the conversion . If a default authority has been set this will also be assigned to each mapping .


public T loginProcessingUrl(String loginProcessingUrl) {
		this.loginProcessingUrl = loginProcessingUrl;
		authFilter
				.setRequiresAuthenticationRequestMatcher(createLoginProcessingUrlMatcher(loginProcessingUrl));
		return getSelf();
	}

public T loginProcessingUrl ( String loginProcessingUrl ) { this . loginProcessingUrl = loginProcessingUrl ; authFilter . setRequiresAuthenticationRequestMatcher ( createLoginProcessingUrlMatcher ( loginProcessingUrl ) ) ; return getSelf ( ) ; }

Specifies the URL to validate the credentials.

@param loginProcessingUrl the URL to validate username and password
@return the {@link FormLoginConfigurer} for additional customization

Specifies the URL to validate the credentials .


protected final void updateAuthenticationDefaults() {
		if (loginProcessingUrl == null) {
			loginProcessingUrl(loginPage);
		}
		if (failureHandler == null) {
			failureUrl(loginPage + "?error");
		}

		final LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(
				LogoutConfigurer.class);
		if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {
			logoutConfigurer.logoutSuccessUrl(loginPage + "?logout");
		}
	}

protected final void updateAuthenticationDefaults ( ) { if ( loginProcessingUrl == null ) { loginProcessingUrl ( loginPage ) ; } if ( failureHandler == null ) { failureUrl ( loginPage + "?error" ) ; } final LogoutConfigurer < B > logoutConfigurer = getBuilder ( ) . getConfigurer ( LogoutConfigurer . class ) ; if ( logoutConfigurer != null && ! logoutConfigurer . isCustomLogoutSuccess ( ) ) { logoutConfigurer . logoutSuccessUrl ( loginPage + "?logout" ) ; } }

Updates the default values for authentication.

@throws Exception

Updates the default values for authentication .


protected final void updateAccessDefaults(B http) {
		if (permitAll) {
			PermitAllSupport.permitAll(http, loginPage, loginProcessingUrl, failureUrl);
		}
	}

protected final void updateAccessDefaults ( B http ) { if ( permitAll ) { PermitAllSupport . permitAll ( http , loginPage , loginProcessingUrl , failureUrl ) ; } }


protected String mapPassword(Object passwordValue) {

		if (!(passwordValue instanceof String)) {
			// Assume it's binary
			passwordValue = new String((byte[]) passwordValue);
		}

		return (String) passwordValue;

	}

protected
String
mapPassword
(
Object
passwordValue
)
{
if
(
!
(
passwordValue
instanceof
String
)
)
{
// Assume it's binary
passwordValue
=
new
String
(
(
byte
[
]
)
passwordValue
)
;
}
return
(
String
)
passwordValue
;
}

Extension point to allow customized creation of the user's password from the
attribute stored in the directory.

@param passwordValue the value of the password attribute
@return a String representation of the password.

Extension point to allow customized creation of the user s password from the attribute stored in the directory .


protected String extractRememberMeCookie(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();

		if ((cookies == null) || (cookies.length == 0)) {
			return null;
		}

		for (Cookie cookie : cookies) {
			if (cookieName.equals(cookie.getName())) {
				return cookie.getValue();
			}
		}

		return null;
	}

protected String extractRememberMeCookie ( HttpServletRequest request ) { Cookie [ ] cookies = request . getCookies ( ) ; if ( ( cookies == null ) || ( cookies . length == 0 ) ) { return null ; } for ( Cookie cookie : cookies ) { if ( cookieName . equals ( cookie . getName ( ) ) ) { return cookie . getValue ( ) ; } } return null ; }

Locates the Spring Security remember me cookie in the request and returns its
value. The cookie is searched for by name and also by matching the context path to
the cookie path.

@param request the submitted request which is to be authenticated
@return the cookie value (if present), null otherwise.

Locates the Spring Security remember me cookie in the request and returns its value . The cookie is searched for by name and also by matching the context path to the cookie path .


protected String encodeCookie(String[] cookieTokens) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < cookieTokens.length; i++) {
			try
			{
				sb.append(URLEncoder.encode(cookieTokens[i], StandardCharsets.UTF_8.toString()));
			}
			catch (UnsupportedEncodingException e)
			{
				logger.error(e.getMessage(), e);
			}

			if (i < cookieTokens.length - 1) {
				sb.append(DELIMITER);
			}
		}

		String value = sb.toString();

		sb = new StringBuilder(new String(Base64.getEncoder().encode(value.getBytes())));

		while (sb.charAt(sb.length() - 1) == '=') {
			sb.deleteCharAt(sb.length() - 1);
		}

		return sb.toString();
	}

protected String encodeCookie ( String [ ] cookieTokens ) { StringBuilder sb = new StringBuilder ( ) ; for ( int i = 0 ; i < cookieTokens . length ; i ++ ) { try { sb . append ( URLEncoder . encode ( cookieTokens [ i ] , StandardCharsets . UTF_8 . toString ( ) ) ) ; } catch ( UnsupportedEncodingException e ) { logger . error ( e . getMessage ( ) , e ) ; } if ( i < cookieTokens . length - 1 ) { sb . append ( DELIMITER ) ; } } String value = sb . toString ( ) ; sb = new StringBuilder ( new String ( Base64 . getEncoder ( ) . encode ( value . getBytes ( ) ) ) ) ; while ( sb . charAt ( sb . length ( ) - 1 ) == ' ' ) { sb . deleteCharAt ( sb . length ( ) - 1 ) ; } return sb . toString ( ) ; }

Inverse operation of decodeCookie.

@param cookieTokens the tokens to be encoded.
@return base64 encoding of the tokens concatenated with the ":" delimiter.


protected void setCookie(String[] tokens, int maxAge, HttpServletRequest request,
			HttpServletResponse response) {
		String cookieValue = encodeCookie(tokens);
		Cookie cookie = new Cookie(cookieName, cookieValue);
		cookie.setMaxAge(maxAge);
		cookie.setPath(getCookiePath(request));
		if (cookieDomain != null) {
			cookie.setDomain(cookieDomain);
		}
		if (maxAge < 1) {
			cookie.setVersion(1);
		}

		if (useSecureCookie == null) {
			cookie.setSecure(request.isSecure());
		}
		else {
			cookie.setSecure(useSecureCookie);
		}

		cookie.setHttpOnly(true);

		response.addCookie(cookie);
	}

protected void setCookie ( String [ ] tokens , int maxAge , HttpServletRequest request , HttpServletResponse response ) { String cookieValue = encodeCookie ( tokens ) ; Cookie cookie = new Cookie ( cookieName , cookieValue ) ; cookie . setMaxAge ( maxAge ) ; cookie . setPath ( getCookiePath ( request ) ) ; if ( cookieDomain != null ) { cookie . setDomain ( cookieDomain ) ; } if ( maxAge < 1 ) { cookie . setVersion ( 1 ) ; } if ( useSecureCookie == null ) { cookie . setSecure ( request . isSecure ( ) ) ; } else { cookie . setSecure ( useSecureCookie ) ; } cookie . setHttpOnly ( true ) ; response . addCookie ( cookie ) ; }

Sets the cookie on the response.

By default a secure cookie will be used if the connection is secure. You can set
the {@code useSecureCookie} property to {@code false} to override this. If you set
it to {@code true}, the cookie will always be flagged as secure. By default the cookie
will be marked as HttpOnly.

@param tokens the tokens which will be encoded to make the cookie value.
@param maxAge the value passed to {@link Cookie#setMaxAge(int)}
@param request the request
@param response the response to add the cookie to.


@Override
	public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext,
			ServerWebExchange exchange) {
		ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
		Mono<SecurityContext> reactiveSecurityContext = ReactiveSecurityContextHolder.getContext();
		if (reactiveSecurityContext == null) {
			return null;
		}
		return reactiveSecurityContext.flatMap( a -> {
			Object p = resolveSecurityContext(parameter, a);
			Mono<Object> o = Mono.justOrEmpty(p);
			return adapter == null ? o : Mono.just(adapter.fromPublisher(o));
		});

	}

@ Override public Mono < Object > resolveArgument ( MethodParameter parameter , BindingContext bindingContext , ServerWebExchange exchange ) { ReactiveAdapter adapter = getAdapterRegistry ( ) . getAdapter ( parameter . getParameterType ( ) ) ; Mono < SecurityContext > reactiveSecurityContext = ReactiveSecurityContextHolder . getContext ( ) ; if ( reactiveSecurityContext == null ) { return null ; } return reactiveSecurityContext . flatMap ( a -> { Object p = resolveSecurityContext ( parameter , a ) ; Mono < Object > o = Mono . justOrEmpty ( p ) ; return adapter == null ? o : Mono . just ( adapter . fromPublisher ( o ) ) ; } ) ; }

resolve the argument to inject into the controller parameter.
@param parameter the method parameter.
@param bindingContext the binding context.
@param exchange the server web exchange.
@return the reactive mono object result.

resolve the argument to inject into the controller parameter .


private String getQueryString(final HttpServletRequest request,
			final Pattern artifactPattern) {
		final String query = request.getQueryString();
		if (query == null) {
			return null;
		}
		final String result = artifactPattern.matcher(query).replaceFirst("");
		if (result.length() == 0) {
			return null;
		}
		// strip off the trailing & only if the artifact was the first query param
		return result.startsWith("&") ? result.substring(1) : result;
	}

If present, removes the artifactParameterName and the corresponding value from the
query String.
@param request
@return the query String minus the artifactParameterName and the corresponding
value.

If present removes the artifactParameterName and the corresponding value from the query String .


private static int getServicePort(URL casServiceUrl) {
		int port = casServiceUrl.getPort();
		if (port == -1) {
			port = casServiceUrl.getDefaultPort();
		}
		return port;
	}

private static int getServicePort ( URL casServiceUrl ) { int port = casServiceUrl . getPort ( ) ; if ( port == - 1 ) { port = casServiceUrl . getDefaultPort ( ) ; } return port ; }

Gets the port from the casServiceURL ensuring to return the proper value if the
default port is being used.
@param casServiceUrl the casServerUrl to be used (i.e.
"https://example.com/context/login/cas")
@return the port that is configured for the casServerUrl

Gets the port from the casServiceURL ensuring to return the proper value if the default port is being used .


public String getPrincipal() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();

		if (authentication == null) {
			log.warn("No Authentication object set in SecurityContext - returning empty String as Principal");
			return "";
		}

		Object principal = authentication.getPrincipal();

		if (principal instanceof LdapUserDetails) {
			LdapUserDetails details = (LdapUserDetails) principal;
			return details.getDn();
		}
		else if (authentication instanceof AnonymousAuthenticationToken) {
			if (log.isDebugEnabled()) {
				log.debug("Anonymous Authentication, returning empty String as Principal");
			}
			return "";
		}
		else {
			throw new IllegalArgumentException(
					"The principal property of the authentication object"
							+ "needs to be an LdapUserDetails.");
		}
	}

Get the principals of the logged in user, in this case the distinguished name.

@return the distinguished name of the logged in user.

Get the principals of the logged in user in this case the distinguished name .


public void logout(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) {
		Assert.notNull(request, "HttpServletRequest required");
		if (invalidateHttpSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				logger.debug("Invalidating session: " + session.getId());
				session.invalidate();
			}
		}

		if (clearAuthentication) {
			SecurityContext context = SecurityContextHolder.getContext();
			context.setAuthentication(null);
		}

		SecurityContextHolder.clearContext();
	}

public
void
logout
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Authentication
authentication
)
{
Assert
.
notNull
(
request
,
"HttpServletRequest required"
)
;
if
(
invalidateHttpSession
)
{
HttpSession
session
=
request
.
getSession
(
false
)
;
if
(
session
!=
)
{
logger
.
debug
(
"Invalidating session: "
+
session
.
getId
(
)
)
;
session
.
invalidate
(
)
;
}
}
if
(
clearAuthentication
)
{
SecurityContext
context
=
SecurityContextHolder
.
getContext
(
)
;
context
.
setAuthentication
(
)
;
}
SecurityContextHolder
.
clearContext
(
)
;
}

Requires the request to be passed in.

@param request from which to obtain a HTTP session (cannot be null)
@param response not used (can be null)
@param authentication not used (can be null)


public Authentication authenticate(Authentication auth)
			throws AuthenticationException {
		if (!(auth instanceof UsernamePasswordAuthenticationToken)) {
			return null;
		}

		UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth;
		Set<GrantedAuthority> authorities;

		try {
			// Create the LoginContext object, and pass our InternallCallbackHandler
			LoginContext loginContext = createLoginContext(
					new InternalCallbackHandler(auth));

			// Attempt to login the user, the LoginContext will call our
			// InternalCallbackHandler at this point.
			loginContext.login();

			// Create a set to hold the authorities, and add any that have already been
			// applied.
			authorities = new HashSet<>();

			// Get the subject principals and pass them to each of the AuthorityGranters
			Set<Principal> principals = loginContext.getSubject().getPrincipals();

			for (Principal principal : principals) {
				for (AuthorityGranter granter : this.authorityGranters) {
					Set<String> roles = granter.grant(principal);

					// If the granter doesn't wish to grant any authorities, it should
					// return null.
					if ((roles != null) && !roles.isEmpty()) {
						for (String role : roles) {
							authorities.add(new JaasGrantedAuthority(role, principal));
						}
					}
				}
			}

			// Convert the authorities set back to an array and apply it to the token.
			JaasAuthenticationToken result = new JaasAuthenticationToken(
					request.getPrincipal(), request.getCredentials(),
					new ArrayList<>(authorities), loginContext);

			// Publish the success event
			publishSuccessEvent(result);

			// we're done, return the token.
			return result;

		}
		catch (LoginException loginException) {
			AuthenticationException ase = this.loginExceptionResolver
					.resolveException(loginException);

			publishFailureEvent(request, ase);
			throw ase;
		}
	}

Attempts to login the user given the Authentication objects principal and
credential

@param auth The Authentication object to be authenticated.

@return The authenticated Authentication object, with it's grantedAuthorities set.

@throws AuthenticationException This implementation does not handle 'locked' or
'disabled' accounts. This method only throws a AuthenticationServiceException, with
the message of the LoginException that will be thrown, should the
loginContext.login() method fail.


private static String buildProviderUrl(List<String> urls, String baseDn) {
		Assert.notNull(baseDn, "The Base DN for the LDAP server must not be null.");
		Assert.notEmpty(urls, "At least one LDAP server URL must be provided.");

		String trimmedBaseDn = baseDn.trim();
		StringBuilder providerUrl = new StringBuilder();

		for (String serverUrl : urls) {
			String trimmedUrl = serverUrl.trim();
			if ("".equals(trimmedUrl)) {
				continue;
			}

			providerUrl.append(trimmedUrl);
			if (!trimmedUrl.endsWith("/")) {
				providerUrl.append("/");
			}
			providerUrl.append(trimmedBaseDn);
			providerUrl.append(" ");
		}

		return providerUrl.toString();

	}

Builds a Spring LDAP-compliant Provider URL string, i.e. a space-separated list of
LDAP servers with their base DNs. As the base DN must be identical for all servers,
it needs to be supplied only once.

@param urls A list of string values which are LDAP server URLs. An example would be

ldap://ldap.company.com:389

. LDAPS URLs may be used as well, given that Spring Security is able to connect to
the server.
@param baseDn The common Base DN for all provided servers, e.g.

dc=company,dc=com

.
@return A Spring Security/Spring LDAP-compliant Provider URL string.

Builds a Spring LDAP - compliant Provider URL string i . e . a space - separated list of LDAP servers with their base DNs . As the base DN must be identical for all servers it needs to be supplied only once .


public void setContextEnvironmentProperties(Map<String, Object> environment) {
		Assert.notEmpty(environment, "environment must not be empty");
		this.contextEnvironmentProperties = new Hashtable<>(environment);
	}

public
void
setContextEnvironmentProperties
(
Map
<
String
,
Object
>
environment
)
{
Assert
.
notEmpty
(
environment
,
"environment must not be empty"
)
;
this
.
contextEnvironmentProperties
=
new
Hashtable
<>
(
environment
)
;
}

Allows a custom environment properties to be used to create initial LDAP context.

@param environment the additional environment parameters to use when creating the LDAP Context

Allows a custom environment properties to be used to create initial LDAP context .


@Override
	public String getRedirectUrl() {
		return UrlUtils.buildFullRequestUrl(scheme, serverName, serverPort, requestURI,
				queryString);
	}

@ Override public String getRedirectUrl ( ) { return UrlUtils . buildFullRequestUrl ( scheme , serverName , serverPort , requestURI , queryString ) ; }

Indicates the URL that the user agent used for this request.

@return the full URL of this request

Indicates the URL that the user agent used for this request .


public int doEndTag() throws JspException {
		try {
			if (!authorized && TagLibConfig.isUiSecurityDisabled()) {
				pageContext.getOut().write(TagLibConfig.getSecuredUiSuffix());
			}
		}
		catch (IOException e) {
			throw new JspException(e);
		}

		return EVAL_PAGE;
	}

public int doEndTag ( ) throws JspException { try { if ( ! authorized && TagLibConfig . isUiSecurityDisabled ( ) ) { pageContext . getOut ( ) . write ( TagLibConfig . getSecuredUiSuffix ( ) ) ; } } catch ( IOException e ) { throw new JspException ( e ) ; } return EVAL_PAGE ; }

Default processing of the end tag returning EVAL_PAGE.

@return EVAL_PAGE
@see Tag#doEndTag()

Default processing of the end tag returning EVAL_PAGE .


@Override
	protected void initUserDetailsService() throws Exception {
		for (UserDetailsBuilder userBuilder : userBuilders) {
			getUserDetailsService().createUser(userBuilder.build());
		}
		for (UserDetails userDetails : this.users) {
			getUserDetailsService().createUser(userDetails);
		}
	}

@ Override protected void initUserDetailsService ( ) throws Exception { for ( UserDetailsBuilder userBuilder : userBuilders ) { getUserDetailsService ( ) . createUser ( userBuilder . build ( ) ) ; } for ( UserDetails userDetails : this . users ) { getUserDetailsService ( ) . createUser ( userDetails ) ; } }

Populates the users that have been added.

@throws Exception

Populates the users that have been added .


private UserDetailsService getUserDetailsService() {
		Map<String, ?> beans = getBeansOfType(CachingUserDetailsService.class);

		if (beans.size() == 0) {
			beans = getBeansOfType(UserDetailsService.class);
		}

		if (beans.size() == 0) {
			throw new ApplicationContextException("No UserDetailsService registered.");

		}
		else if (beans.size() > 1) {
			throw new ApplicationContextException(
					"More than one UserDetailsService registered. Please "
							+ "use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
		}

		return (UserDetailsService) beans.values().toArray()[0];
	}

Obtains a user details service for use in RememberMeServices etc. Will return a
caching version if available so should not be used for beans which need to separate
the two.

Obtains a user details service for use in RememberMeServices etc . Will return a caching version if available so should not be used for beans which need to separate the two .


private void addPkceParameters(Map<String, Object> attributes, Map<String, Object> additionalParameters) {
		String codeVerifier = this.codeVerifierGenerator.generateKey();
		attributes.put(PkceParameterNames.CODE_VERIFIER, codeVerifier);
		try {
			String codeChallenge = createCodeChallenge(codeVerifier);
			additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge);
			additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256");
		} catch (NoSuchAlgorithmException e) {
			additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier);
		}
	}

private void addPkceParameters ( Map < String , Object > attributes , Map < String , Object > additionalParameters ) { String codeVerifier = this . codeVerifierGenerator . generateKey ( ) ; attributes . put ( PkceParameterNames . CODE_VERIFIER , codeVerifier ) ; try { String codeChallenge = createCodeChallenge ( codeVerifier ) ; additionalParameters . put ( PkceParameterNames . CODE_CHALLENGE , codeChallenge ) ; additionalParameters . put ( PkceParameterNames . CODE_CHALLENGE_METHOD , "S256" ) ; } catch ( NoSuchAlgorithmException e ) { additionalParameters . put ( PkceParameterNames . CODE_CHALLENGE , codeVerifier ) ; } }

Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization and Access Token Requests

@param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the token request
@param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, usually,
{@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in the authorization request.

@since 5.2
@see 1.1.  Protocol Flow
@see 4.1.  Client Creates a Code Verifier
@see 4.2.  Client Creates the Code Challenge

Creates and adds additional PKCE parameters for use in the OAuth 2 . 0 Authorization and Access Token Requests


protected boolean requiresAuthentication(final HttpServletRequest request,
			final HttpServletResponse response) {
		final boolean serviceTicketRequest = serviceTicketRequest(request, response);
		final boolean result = serviceTicketRequest || proxyReceptorRequest(request)
				|| (proxyTicketRequest(serviceTicketRequest, request));
		if (logger.isDebugEnabled()) {
			logger.debug("requiresAuthentication = " + result);
		}
		return result;
	}

protected
boolean
requiresAuthentication
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
)
{
final
boolean
serviceTicketRequest
=
serviceTicketRequest
(
request
,
response
)
;
final
boolean
result
=
serviceTicketRequest
||
proxyReceptorRequest
(
request
)
||
(
proxyTicketRequest
(
serviceTicketRequest
,
request
)
)
;
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"requiresAuthentication = "
+
result
)
;
}
return
result
;
}

Overridden to provide proxying capabilities.

Overridden to provide proxying capabilities .


private boolean serviceTicketRequest(final HttpServletRequest request,
			final HttpServletResponse response) {
		boolean result = super.requiresAuthentication(request, response);
		if (logger.isDebugEnabled()) {
			logger.debug("serviceTicketRequest = " + result);
		}
		return result;
	}

private
boolean
serviceTicketRequest
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
)
{
boolean
result
=
super
.
requiresAuthentication
(
request
,
response
)
;
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"serviceTicketRequest = "
+
result
)
;
}
return
result
;
}

Indicates if the request is elgible to process a service ticket. This method exists
for readability.
@param request
@param response
@return

Indicates if the request is elgible to process a service ticket . This method exists for readability .


private boolean proxyTicketRequest(final boolean serviceTicketRequest,
			final HttpServletRequest request) {
		if (serviceTicketRequest) {
			return false;
		}
		final boolean result = authenticateAllArtifacts
				&& obtainArtifact(request) != null && !authenticated();
		if (logger.isDebugEnabled()) {
			logger.debug("proxyTicketRequest = " + result);
		}
		return result;
	}

private
boolean
proxyTicketRequest
(
final
boolean
serviceTicketRequest
,
final
HttpServletRequest
request
)
{
if
(
serviceTicketRequest
)
{
return
false
;
}
final
boolean
result
=
authenticateAllArtifacts
&&
obtainArtifact
(
request
)
!=
&&
!
authenticated
(
)
;
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"proxyTicketRequest = "
+
result
)
;
}
return
result
;
}

Indicates if the request is elgible to process a proxy ticket.
@param request
@return

Indicates if the request is elgible to process a proxy ticket .


private boolean authenticated() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		return authentication != null && authentication.isAuthenticated()
				&& !(authentication instanceof AnonymousAuthenticationToken);
	}

private boolean authenticated ( ) { Authentication authentication = SecurityContextHolder . getContext ( ) . getAuthentication ( ) ; return authentication != null && authentication . isAuthenticated ( ) && ! ( authentication instanceof AnonymousAuthenticationToken ) ; }

Determines if a user is already authenticated.
@return

Determines if a user is already authenticated .


private boolean proxyReceptorRequest(final HttpServletRequest request) {
		final boolean result = proxyReceptorConfigured()
				&& proxyReceptorMatcher.matches(request);
		if (logger.isDebugEnabled()) {
			logger.debug("proxyReceptorRequest = " + result);
		}
		return result;
	}

private
boolean
proxyReceptorRequest
(
final
HttpServletRequest
request
)
{
final
boolean
result
=
proxyReceptorConfigured
(
)
&&
proxyReceptorMatcher
.
matches
(
request
)
;
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"proxyReceptorRequest = "
+
result
)
;
}
return
result
;
}

Indicates if the request is elgible to be processed as the proxy receptor.
@param request
@return

Indicates if the request is elgible to be processed as the proxy receptor .


protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
			Authentication authentication, MethodInvocation invocation) {
		MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(
				authentication);
		root.setThis(invocation.getThis());
		root.setPermissionEvaluator(getPermissionEvaluator());
		root.setTrustResolver(getTrustResolver());
		root.setRoleHierarchy(getRoleHierarchy());
		root.setDefaultRolePrefix(getDefaultRolePrefix());

		return root;
	}

protected MethodSecurityExpressionOperations createSecurityExpressionRoot ( Authentication authentication , MethodInvocation invocation ) { MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot ( authentication ) ; root . setThis ( invocation . getThis ( ) ) ; root . setPermissionEvaluator ( getPermissionEvaluator ( ) ) ; root . setTrustResolver ( getTrustResolver ( ) ) ; root . setRoleHierarchy ( getRoleHierarchy ( ) ) ; root . setDefaultRolePrefix ( getDefaultRolePrefix ( ) ) ; return root ; }

Creates the root object for expression evaluation.

Creates the root object for expression evaluation .


private Mono<JWKSet> getJWKSet() {
		return this.webClient.get()
				.uri(this.jwkSetURL)
				.retrieve()
				.bodyToMono(String.class)
				.map(this::parse)
				.doOnNext(jwkSet -> this.cachedJWKSet.set(Mono.just(jwkSet)))
				.cache();
	}

private Mono < JWKSet > getJWKSet ( ) { return this . webClient . get ( ) . uri ( this . jwkSetURL ) . retrieve ( ) . bodyToMono ( String . class ) . map ( this :: parse ) . doOnNext ( jwkSet -> this . cachedJWKSet . set ( Mono . just ( jwkSet ) ) ) . cache ( ) ; }

Updates the cached JWK set from the configured URL.

@return The updated JWK set.

@throws RemoteKeySourceException If JWK retrieval failed.

Updates the cached JWK set from the configured URL .


private String utf8UrlEncode(String value) {
		try {
			return URLEncoder.encode(value, "UTF-8");
		}
		catch (UnsupportedEncodingException e) {
			Error err = new AssertionError(
					"The Java platform guarantees UTF-8 support, but it seemingly is not present.");
			err.initCause(e);
			throw err;
		}
	}

Performs URL encoding with UTF-8

@param value the value to URL encode
@return the encoded value


private Collection<? extends GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
		List<String> webSphereGroups = wasHelper.getGroupsForCurrentUser();
		Collection<? extends GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper
				.getGrantedAuthorities(webSphereGroups);
		if (logger.isDebugEnabled()) {
			logger.debug("WebSphere groups: " + webSphereGroups
					+ " mapped to Granted Authorities: " + userGas);
		}
		return userGas;
	}

Get a list of Granted Authorities based on the current user's WebSphere groups.

@return authorities mapped from the user's WebSphere groups.

Get a list of Granted Authorities based on the current user s WebSphere groups .


protected UserDetails loadUserByAssertion(final Assertion assertion) {
		final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(
				assertion, "");
		return this.authenticationUserDetailsService.loadUserDetails(token);
	}

protected UserDetails loadUserByAssertion ( final Assertion assertion ) { final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken ( assertion , "" ) ; return this . authenticationUserDetailsService . loadUserDetails ( token ) ; }

Template method for retrieving the UserDetails based on the assertion. Default is
to call configured userDetailsService and pass the username. Deployers can override
this method and retrieve the user based on any criteria they desire.

@param assertion The CAS Assertion.
@return the UserDetails.

Template method for retrieving the UserDetails based on the assertion . Default is to call configured userDetailsService and pass the username . Deployers can override this method and retrieve the user based on any criteria they desire .


protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
		Object principal = wasHelper.getCurrentUserName();
		if (logger.isDebugEnabled()) {
			logger.debug("PreAuthenticated WebSphere principal: " + principal);
		}
		return principal;
	}


public static byte[] concatenate(byte[]... arrays) {
		int length = 0;
		for (byte[] array : arrays) {
			length += array.length;
		}
		byte[] newArray = new byte[length];
		int destPos = 0;
		for (byte[] array : arrays) {
			System.arraycopy(array, 0, newArray, destPos, array.length);
			destPos += array.length;
		}
		return newArray;
	}

public static byte [ ] concatenate ( byte [ ] ... arrays ) { int length = 0 ; for ( byte [ ] array : arrays ) { length += array . length ; } byte [ ] newArray = new byte [ length ] ; int destPos = 0 ; for ( byte [ ] array : arrays ) { System . arraycopy ( array , 0 , newArray , destPos , array . length ) ; destPos += array . length ; } return newArray ; }

Combine the individual byte arrays into one array.

Combine the individual byte arrays into one array .


public static byte[] subArray(byte[] array, int beginIndex, int endIndex) {
		int length = endIndex - beginIndex;
		byte[] subarray = new byte[length];
		System.arraycopy(array, beginIndex, subarray, 0, length);
		return subarray;
	}

public static byte [ ] subArray ( byte [ ] array , int beginIndex , int endIndex ) { int length = endIndex - beginIndex ; byte [ ] subarray = new byte [ length ] ; System . arraycopy ( array , beginIndex , subarray , 0 , length ) ; return subarray ; }

Extract a sub array of bytes out of the byte array.
@param array the byte array to extract from
@param beginIndex the beginning index of the sub array, inclusive
@param endIndex the ending index of the sub array, exclusive

Extract a sub array of bytes out of the byte array .


public List<GrantedAuthority> getGrantedAuthorities(Collection<String> attributes) {
		ArrayList<GrantedAuthority> gaList = new ArrayList<>();
		for (String attribute : attributes) {
			Collection<GrantedAuthority> c = attributes2grantedAuthoritiesMap
					.get(attribute);
			if (c != null) {
				gaList.addAll(c);
			}
		}
		gaList.trimToSize();

		return gaList;
	}

public List < GrantedAuthority > getGrantedAuthorities ( Collection < String > attributes ) { ArrayList < GrantedAuthority > gaList = new ArrayList <> ( ) ; for ( String attribute : attributes ) { Collection < GrantedAuthority > c = attributes2grantedAuthoritiesMap . get ( attribute ) ; if ( c != null ) { gaList . addAll ( c ) ; } } gaList . trimToSize ( ) ; return gaList ; }

Map the given array of attributes to Spring Security GrantedAuthorities.

Map the given array of attributes to Spring Security GrantedAuthorities .


private Map<String, Collection<GrantedAuthority>> preProcessMap(Map<?, ?> orgMap) {
		Map<String, Collection<GrantedAuthority>> result = new HashMap<String, Collection<GrantedAuthority>>(
				orgMap.size());

		for (Map.Entry<?, ?> entry : orgMap.entrySet()) {
			Assert.isInstanceOf(String.class, entry.getKey(),
					"attributes2grantedAuthoritiesMap contains non-String objects as keys");
			result.put((String) entry.getKey(),
					getGrantedAuthorityCollection(entry.getValue()));
		}
		return result;
	}

Preprocess the given map to convert all the values to GrantedAuthority collections

@param orgMap The map to process
@return the processed Map


private Collection<GrantedAuthority> getGrantedAuthorityCollection(Object value) {
		Collection<GrantedAuthority> result = new ArrayList<>();
		addGrantedAuthorityCollection(result, value);
		return result;
	}

private Collection < GrantedAuthority > getGrantedAuthorityCollection ( Object value ) { Collection < GrantedAuthority > result = new ArrayList <> ( ) ; addGrantedAuthorityCollection ( result , value ) ; return result ; }

Convert the given value to a collection of Granted Authorities

@param value The value to convert to a GrantedAuthority Collection
@return Collection containing the GrantedAuthority Collection


private void addGrantedAuthorityCollection(Collection<GrantedAuthority> result,
			Object value) {
		if (value == null) {
			return;
		}
		if (value instanceof Collection<?>) {
			addGrantedAuthorityCollection(result, (Collection<?>) value);
		}
		else if (value instanceof Object[]) {
			addGrantedAuthorityCollection(result, (Object[]) value);
		}
		else if (value instanceof String) {
			addGrantedAuthorityCollection(result, (String) value);
		}
		else if (value instanceof GrantedAuthority) {
			result.add((GrantedAuthority) value);
		}
		else {
			throw new IllegalArgumentException("Invalid object type: "
					+ value.getClass().getName());
		}
	}

private
void
addGrantedAuthorityCollection
(
Collection
<
GrantedAuthority
>
result
,
Object
value
)
{
if
(
value
==
)
{
return
;
}
if
(
value
instanceof
Collection
<
>
)
{
addGrantedAuthorityCollection
(
result
,
(
Collection
<
>
)
value
)
;
}
else
if
(
value
instanceof
Object
[
]
)
{
addGrantedAuthorityCollection
(
result
,
(
Object
[
]
)
value
)
;
}
else
if
(
value
instanceof
String
)
{
addGrantedAuthorityCollection
(
result
,
(
String
)
value
)
;
}
else
if
(
value
instanceof
GrantedAuthority
)
{
result
.
add
(
(
GrantedAuthority
)
value
)
;
}
else
{
throw
new
IllegalArgumentException
(
"Invalid object type: "
+
value
.
getClass
(
)
.
getName
(
)
)
;
}
}

Convert the given value to a collection of Granted Authorities, adding the result
to the given result collection.

@param value The value to convert to a GrantedAuthority Collection
@return Collection containing the GrantedAuthority Collection

Convert the given value to a collection of Granted Authorities adding the result to the given result collection .


protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
		Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest
				.getUserPrincipal().getName();
		if (logger.isDebugEnabled()) {
			logger.debug("PreAuthenticated J2EE principal: " + principal);
		}
		return principal;
	}

protected
Object
getPreAuthenticatedPrincipal
(
HttpServletRequest
httpRequest
)
{
Object
principal
=
httpRequest
.
getUserPrincipal
(
)
==
:
httpRequest
.
getUserPrincipal
(
)
.
getName
(
)
;
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"PreAuthenticated J2EE principal: "
+
principal
)
;
}
return
principal
;
}


@SuppressWarnings("unchecked")
	public <C> C getSharedObject(Class<C> sharedType) {
		return (C) this.sharedObjects.get(sharedType);
	}

@ SuppressWarnings ( "unchecked" ) public < C > C getSharedObject ( Class < C > sharedType ) { return ( C ) this . sharedObjects . get ( sharedType ) ; }

Gets a shared Object. Note that object heirarchies are not considered.

@param sharedType the type of the shared Object
@return the shared Object or null if it is not found

Gets a shared Object . Note that object heirarchies are not considered .


protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request)
			throws IOException, ServletException {

		int serverPort = portResolver.getServerPort(request);
		Integer httpsPort = portMapper.lookupHttpsPort(Integer.valueOf(serverPort));

		if (httpsPort != null) {
			RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
			urlBuilder.setScheme("https");
			urlBuilder.setServerName(request.getServerName());
			urlBuilder.setPort(httpsPort.intValue());
			urlBuilder.setContextPath(request.getContextPath());
			urlBuilder.setServletPath(request.getServletPath());
			urlBuilder.setPathInfo(request.getPathInfo());
			urlBuilder.setQuery(request.getQueryString());

			return urlBuilder.getUrl();
		}

		// Fall through to server-side forward with warning message
		logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port "
				+ serverPort);

		return null;
	}

Builds a URL to redirect the supplied request to HTTPS. Used to redirect the
current request to HTTPS, before doing a forward to the login page.

Builds a URL to redirect the supplied request to HTTPS . Used to redirect the current request to HTTPS before doing a forward to the login page .


public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) {
		InterceptorStatusToken token = super
				.beforeInvocation(new MethodInvocationAdapter(jp));

		Object result;
		try {
			result = advisorProceed.proceedWithObject();
		}
		finally {
			super.finallyInvocation(token);
		}

		return super.afterInvocation(token, result);
	}

public Object invoke ( JoinPoint jp , AspectJCallback advisorProceed ) { InterceptorStatusToken token = super . beforeInvocation ( new MethodInvocationAdapter ( jp ) ) ; Object result ; try { result = advisorProceed . proceedWithObject ( ) ; } finally { super . finallyInvocation ( token ) ; } return super . afterInvocation ( token , result ) ; }

Method that is suitable for user with traditional AspectJ-code aspects.

@param jp The AspectJ joint point being invoked which requires a security decision
@param advisorProceed the advice-defined anonymous class that implements
{@code AspectJCallback} containing a simple {@code return proceed();} statement

@return The returned value from the method invocation

Method that is suitable for user with traditional AspectJ - code aspects .


private static String hasRole(String role) {
		Assert.isTrue(
				!role.startsWith("ROLE_"),
				() -> role
						+ " should not start with ROLE_ since ROLE_ is automatically prepended when using hasRole. Consider using hasAuthority or access instead.");
		return "ROLE_" + role;
	}

Creates a String for specifying a user requires a role.

@param role the role that should be required which is prepended with ROLE_
automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_
@return the {@link ConfigAttribute} expressed as a String

Creates a String for specifying a user requires a role .


private static String[] hasAnyRole(String... roles) {
		for (int i = 0; i < roles.length; i++) {
			roles[i] = "ROLE_" + roles[i];
		}
		return roles;
	}

private static String [ ] hasAnyRole ( String ... roles ) { for ( int i = 0 ; i < roles . length ; i ++ ) { roles [ i ] = "ROLE_" + roles [ i ] ; } return roles ; }

Creates a String for specifying that a user requires one of many roles.

@param roles the roles that the user should have at least one of (i.e. ADMIN, USER,
etc). Each role should not start with ROLE_ since it is automatically prepended
already.
@return the {@link ConfigAttribute} expressed as a String

Creates a String for specifying that a user requires one of many roles .


protected UserDetails processAutoLoginCookie(String[] cookieTokens,
			HttpServletRequest request, HttpServletResponse response) {

		if (cookieTokens.length != 2) {
			throw new InvalidCookieException("Cookie token did not contain " + 2
					+ " tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
		}

		final String presentedSeries = cookieTokens[0];
		final String presentedToken = cookieTokens[1];

		PersistentRememberMeToken token = tokenRepository
				.getTokenForSeries(presentedSeries);

		if (token == null) {
			// No series match, so we can't authenticate using this cookie
			throw new RememberMeAuthenticationException(
					"No persistent token found for series id: " + presentedSeries);
		}

		// We have a match for this user/series combination
		if (!presentedToken.equals(token.getTokenValue())) {
			// Token doesn't match series value. Delete all logins for this user and throw
			// an exception to warn them.
			tokenRepository.removeUserTokens(token.getUsername());

			throw new CookieTheftException(
					messages.getMessage(
							"PersistentTokenBasedRememberMeServices.cookieStolen",
							"Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."));
		}

		if (token.getDate().getTime() + getTokenValiditySeconds() * 1000L < System
				.currentTimeMillis()) {
			throw new RememberMeAuthenticationException("Remember-me login has expired");
		}

		// Token also matches, so login is valid. Update the token value, keeping the
		// *same* series number.
		if (logger.isDebugEnabled()) {
			logger.debug("Refreshing persistent login token for user '"
					+ token.getUsername() + "', series '" + token.getSeries() + "'");
		}

		PersistentRememberMeToken newToken = new PersistentRememberMeToken(
				token.getUsername(), token.getSeries(), generateTokenData(), new Date());

		try {
			tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(),
					newToken.getDate());
			addCookie(newToken, request, response);
		}
		catch (Exception e) {
			logger.error("Failed to update token: ", e);
			throw new RememberMeAuthenticationException(
					"Autologin failed due to data access problem");
		}

		return getUserDetailsService().loadUserByUsername(token.getUsername());
	}

Locates the presented cookie data in the token repository, using the series id. If
the data compares successfully with that in the persistent store, a new token is
generated and stored with the same series. The corresponding cookie value is set on
the response.

@param cookieTokens the series and token values

@throws RememberMeAuthenticationException if there is no stored token corresponding
to the submitted cookie, or if the token in the persistent store has expired.
@throws InvalidCookieException if the cookie doesn't have two tokens as expected.
@throws CookieTheftException if a presented series value is found, but the stored
token is different from the one presented.

Locates the presented cookie data in the token repository using the series id . If the data compares successfully with that in the persistent store a new token is generated and stored with the same series . The corresponding cookie value is set on the response .


protected void onLoginSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication successfulAuthentication) {
		String username = successfulAuthentication.getName();

		logger.debug("Creating new persistent login for user " + username);

		PersistentRememberMeToken persistentToken = new PersistentRememberMeToken(
				username, generateSeriesData(), generateTokenData(), new Date());
		try {
			tokenRepository.createNewToken(persistentToken);
			addCookie(persistentToken, request, response);
		}
		catch (Exception e) {
			logger.error("Failed to save persistent token ", e);
		}
	}

Creates a new persistent login token with a new series number, stores the data in
the persistent token repository and adds the corresponding cookie to the response.

Creates a new persistent login token with a new series number stores the data in the persistent token repository and adds the corresponding cookie to the response .


protected Authentication attemptSwitchUser(HttpServletRequest request)
			throws AuthenticationException {
		UsernamePasswordAuthenticationToken targetUserRequest;

		String username = request.getParameter(this.usernameParameter);

		if (username == null) {
			username = "";
		}

		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Attempt to switch to user [" + username + "]");
		}

		UserDetails targetUser = this.userDetailsService.loadUserByUsername(username);
		this.userDetailsChecker.check(targetUser);

		// OK, create the switch user token
		targetUserRequest = createSwitchUserToken(request, targetUser);

		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Switch User Token [" + targetUserRequest + "]");
		}

		// publish event
		if (this.eventPublisher != null) {
			this.eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(
					SecurityContextHolder.getContext().getAuthentication(), targetUser));
		}

		return targetUserRequest;
	}

protected
Authentication
attemptSwitchUser
(
HttpServletRequest
request
)
throws
AuthenticationException
{
UsernamePasswordAuthenticationToken
targetUserRequest
;
String
username
=
request
.
getParameter
(
this
.
usernameParameter
)
;
if
(
username
==
)
{
username
=
""
;
}
if
(
this
.
logger
.
isDebugEnabled
(
)
)
{
this
.
logger
.
debug
(
"Attempt to switch to user ["
+
username
+
"]"
)
;
}
UserDetails
targetUser
=
this
.
userDetailsService
.
loadUserByUsername
(
username
)
;
this
.
userDetailsChecker
.
check
(
targetUser
)
;
// OK, create the switch user token
targetUserRequest
=
createSwitchUserToken
(
request
,
targetUser
)
;
if
(
this
.
logger
.
isDebugEnabled
(
)
)
{
this
.
logger
.
debug
(
"Switch User Token ["
+
targetUserRequest
+
"]"
)
;
}
// publish event
if
(
this
.
eventPublisher
!=
)
{
this
.
eventPublisher
.
publishEvent
(
new
AuthenticationSwitchUserEvent
(
SecurityContextHolder
.
getContext
(
)
.
getAuthentication
(
)
,
targetUser
)
)
;
}
return
targetUserRequest
;
}

Attempt to switch to another user. If the user does not exist or is not active,
return null.

@return The new Authentication request if successfully switched to
another user, null otherwise.

@throws UsernameNotFoundException If the target user is not found.
@throws LockedException if the account is locked.
@throws DisabledException If the target user is disabled.
@throws AccountExpiredException If the target user account is expired.
@throws CredentialsExpiredException If the target user credentials are expired.

Attempt to switch to another user . If the user does not exist or is not active return null .


protected Authentication attemptExitUser(HttpServletRequest request)
			throws AuthenticationCredentialsNotFoundException {
		// need to check to see if the current user has a SwitchUserGrantedAuthority
		Authentication current = SecurityContextHolder.getContext().getAuthentication();

		if (null == current) {
			throw new AuthenticationCredentialsNotFoundException(
					this.messages.getMessage("SwitchUserFilter.noCurrentUser",
							"No current user associated with this request"));
		}

		// check to see if the current user did actual switch to another user
		// if so, get the original source user so we can switch back
		Authentication original = getSourceAuthentication(current);

		if (original == null) {
			this.logger.debug("Could not find original user Authentication object!");
			throw new AuthenticationCredentialsNotFoundException(
					this.messages.getMessage("SwitchUserFilter.noOriginalAuthentication",
							"Could not find original Authentication object"));
		}

		// get the source user details
		UserDetails originalUser = null;
		Object obj = original.getPrincipal();

		if ((obj != null) && obj instanceof UserDetails) {
			originalUser = (UserDetails) obj;
		}

		// publish event
		if (this.eventPublisher != null) {
			this.eventPublisher.publishEvent(
					new AuthenticationSwitchUserEvent(current, originalUser));
		}

		return original;
	}

Attempt to exit from an already switched user.

@param request The http servlet request

@return The original Authentication object or null
otherwise.

@throws AuthenticationCredentialsNotFoundException If no
Authentication associated with this request.

Attempt to exit from an already switched user .


public void setExitUserUrl(String exitUserUrl) {
		Assert.isTrue(UrlUtils.isValidRedirectUrl(exitUserUrl),
				"exitUserUrl cannot be empty and must be a valid redirect URL");
		this.exitUserMatcher = createMatcher(exitUserUrl);
	}

Set the URL to respond to exit user processing.

@param exitUserUrl The exit user URL.

Set the URL to respond to exit user processing .


@RequestMapping(value = "/hello.htm", method = RequestMethod.GET)
	public ModelAndView displayPublicIndex() {
		Contact rnd = contactManager.getRandomContact();

		return new ModelAndView("hello", "contact", rnd);
	}

@ RequestMapping ( value = "/hello.htm" , method = RequestMethod . GET ) public ModelAndView displayPublicIndex ( ) { Contact rnd = contactManager . getRandomContact ( ) ; return new ModelAndView ( "hello" , "contact" , rnd ) ; }

The public index page, used for unauthenticated users.

The public index page used for unauthenticated users .


@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
		return webSecurity.build();
	}

Creates the Spring Security Filter Chain
@return the {@link Filter} that represents the security filter chain
@throws Exception


@Override
	public Jwt decode(String token) throws JwtException {
		JWT jwt = parse(token);
		if (jwt instanceof SignedJWT) {
			Jwt createdJwt = createJwt(token, jwt);
			return validateJwt(createdJwt);
		}
		throw new JwtException("Unsupported algorithm of " + jwt.getHeader().getAlgorithm());
	}

@
Override
public
Jwt
decode
(
String
token
)
throws
JwtException
{
JWT
jwt
=
parse
(
token
)
;
if
(
jwt
instanceof
SignedJWT
)
{
Jwt
createdJwt
=
createJwt
(
token
,
jwt
)
;
return
validateJwt
(
createdJwt
)
;
}
throw
new
JwtException
(
"Unsupported algorithm of "
+
jwt
.
getHeader
(
)
.
getAlgorithm
(
)
)
;
}

Decode and validate the JWT from its compact claims representation format

@param token the JWT value
@return a validated {@link Jwt}
@throws JwtException


public boolean authorizeUsingAccessExpression() throws IOException {
		if (SecurityContextHolder.getContext().getAuthentication() == null) {
			return false;
		}

		SecurityExpressionHandler<FilterInvocation> handler = getExpressionHandler();

		Expression accessExpression;
		try {
			accessExpression = handler.getExpressionParser().parseExpression(getAccess());

		}
		catch (ParseException e) {
			IOException ioException = new IOException();
			ioException.initCause(e);
			throw ioException;
		}

		return ExpressionUtils.evaluateAsBoolean(accessExpression,
				createExpressionEvaluationContext(handler));
	}

public boolean authorizeUsingAccessExpression ( ) throws IOException { if ( SecurityContextHolder . getContext ( ) . getAuthentication ( ) == null ) { return false ; } SecurityExpressionHandler < FilterInvocation > handler = getExpressionHandler ( ) ; Expression accessExpression ; try { accessExpression = handler . getExpressionParser ( ) . parseExpression ( getAccess ( ) ) ; } catch ( ParseException e ) { IOException ioException = new IOException ( ) ; ioException . initCause ( e ) ; throw ioException ; } return ExpressionUtils . evaluateAsBoolean ( accessExpression , createExpressionEvaluationContext ( handler ) ) ; }

Make an authorization decision based on a Spring EL expression. See the
"Expression-Based Access Control" chapter in Spring Security for details on what
expressions can be used.

@return the result of the authorization decision
@throws IOException

Make an authorization decision based on a Spring EL expression . See the Expression - Based Access Control chapter in Spring Security for details on what expressions can be used .


public boolean authorizeUsingUrlCheck() throws IOException {
		String contextPath = ((HttpServletRequest) getRequest()).getContextPath();
		Authentication currentUser = SecurityContextHolder.getContext()
				.getAuthentication();
		return getPrivilegeEvaluator().isAllowed(contextPath, getUrl(), getMethod(),
				currentUser);
	}

public boolean authorizeUsingUrlCheck ( ) throws IOException { String contextPath = ( ( HttpServletRequest ) getRequest ( ) ) . getContextPath ( ) ; Authentication currentUser = SecurityContextHolder . getContext ( ) . getAuthentication ( ) ; return getPrivilegeEvaluator ( ) . isAllowed ( contextPath , getUrl ( ) , getMethod ( ) , currentUser ) ; }

Make an authorization decision based on the URL and HTTP method attributes. True is
returned if the user is allowed to access the given URL as defined.

@return the result of the authorization decision
@throws IOException

Make an authorization decision based on the URL and HTTP method attributes . True is returned if the user is allowed to access the given URL as defined .


@Override
	public Collection<GrantedAuthority> convert(Jwt jwt) {
		return getScopes(jwt)
				.stream()
				.map(authority -> SCOPE_AUTHORITY_PREFIX + authority)
				.map(SimpleGrantedAuthority::new)
				.collect(Collectors.toList());
	}

@ Override public Collection < GrantedAuthority > convert ( Jwt jwt ) { return getScopes ( jwt ) . stream ( ) . map ( authority -> SCOPE_AUTHORITY_PREFIX + authority ) . map ( SimpleGrantedAuthority :: new ) . collect ( Collectors . toList ( ) ) ; }

Extracts the authorities
@param jwt The {@link Jwt} token
@return The {@link GrantedAuthority authorities} read from the token scopes


@Override
	public CsrfToken generateToken(HttpServletRequest request) {
		return wrap(request, this.delegate.generateToken(request));
	}

@ Override public CsrfToken generateToken ( HttpServletRequest request ) { return wrap ( request , this . delegate . generateToken ( request ) ) ; }

Generates a new token
@param request the {@link HttpServletRequest} to use. The
{@link HttpServletRequest} must have the {@link HttpServletResponse} as an
attribute with the name of HttpServletResponse.class.getName()


@RequestMapping(value = "/secure/adminPermission.htm", method = RequestMethod.GET)
	public ModelAndView displayAdminPage(@RequestParam("contactId") int contactId) {
		Contact contact = contactManager.getById(Long.valueOf(contactId));
		Acl acl = aclService.readAclById(new ObjectIdentityImpl(contact));

		Map<String, Object> model = new HashMap<>();
		model.put("contact", contact);
		model.put("acl", acl);

		return new ModelAndView("adminPermission", "model", model);
	}

@ RequestMapping ( value = "/secure/adminPermission.htm" , method = RequestMethod . GET ) public ModelAndView displayAdminPage ( @ RequestParam ( "contactId" ) int contactId ) { Contact contact = contactManager . getById ( Long . valueOf ( contactId ) ) ; Acl acl = aclService . readAclById ( new ObjectIdentityImpl ( contact ) ) ; Map < String , Object > model = new HashMap <> ( ) ; model . put ( "contact" , contact ) ; model . put ( "acl" , acl ) ; return new ModelAndView ( "adminPermission" , "model" , model ) ; }

Displays the permission admin page for a particular contact.

Displays the permission admin page for a particular contact .


@RequestMapping(value = "/secure/addPermission.htm", method = RequestMethod.GET)
	public ModelAndView displayAddPermissionPageForContact(
			@RequestParam("contactId") long contactId) {
		Contact contact = contactManager.getById(contactId);

		AddPermission addPermission = new AddPermission();
		addPermission.setContact(contact);

		Map<String, Object> model = new HashMap<>();
		model.put("addPermission", addPermission);
		model.put("recipients", listRecipients());
		model.put("permissions", listPermissions());

		return new ModelAndView("addPermission", model);
	}

@ RequestMapping ( value = "/secure/addPermission.htm" , method = RequestMethod . GET ) public ModelAndView displayAddPermissionPageForContact ( @ RequestParam ( "contactId" ) long contactId ) { Contact contact = contactManager . getById ( contactId ) ; AddPermission addPermission = new AddPermission ( ) ; addPermission . setContact ( contact ) ; Map < String , Object > model = new HashMap <> ( ) ; model . put ( "addPermission" , addPermission ) ; model . put ( "recipients" , listRecipients ( ) ) ; model . put ( "permissions" , listPermissions ( ) ) ; return new ModelAndView ( "addPermission" , model ) ; }

Displays the "add permission" page for a contact.

Displays the add permission page for a contact .


@RequestMapping(value = "/secure/addPermission.htm", method = RequestMethod.POST)
	public String addPermission(AddPermission addPermission, BindingResult result,
			ModelMap model) {
		addPermissionValidator.validate(addPermission, result);

		if (result.hasErrors()) {
			model.put("recipients", listRecipients());
			model.put("permissions", listPermissions());

			return "addPermission";
		}

		PrincipalSid sid = new PrincipalSid(addPermission.getRecipient());
		Permission permission = permissionFactory.buildFromMask(addPermission
				.getPermission());

		try {
			contactManager.addPermission(addPermission.getContact(), sid, permission);
		}
		catch (DataAccessException existingPermission) {
			existingPermission.printStackTrace();
			result.rejectValue("recipient", "err.recipientExistsForContact",
					"Addition failure.");

			model.put("recipients", listRecipients());
			model.put("permissions", listPermissions());
			return "addPermission";
		}

		return "redirect:/secure/index.htm";
	}

@
RequestMapping
(
value
=
"/secure/addPermission.htm"
,
method
=
RequestMethod
.
POST
)
public
String
addPermission
(
AddPermission
addPermission
,
BindingResult
result
,
ModelMap
model
)
{
addPermissionValidator
.
validate
(
addPermission
,
result
)
;
if
(
result
.
hasErrors
(
)
)
{
model
.
put
(
"recipients"
,
listRecipients
(
)
)
;
model
.
put
(
"permissions"
,
listPermissions
(
)
)
;
return
"addPermission"
;
}
PrincipalSid
sid
=
new
PrincipalSid
(
addPermission
.
getRecipient
(
)
)
;
Permission
permission
=
permissionFactory
.
buildFromMask
(
addPermission
.
getPermission
(
)
)
;
try
{
contactManager
.
addPermission
(
addPermission
.
getContact
(
)
,
sid
,
permission
)
;
}
catch
(
DataAccessException
existingPermission
)
{
existingPermission
.
printStackTrace
(
)
;
result
.
rejectValue
(
"recipient"
,
"err.recipientExistsForContact"
,
"Addition failure."
)
;
model
.
put
(
"recipients"
,
listRecipients
(
)
)
;
model
.
put
(
"permissions"
,
listPermissions
(
)
)
;
return
"addPermission"
;
}
return
"redirect:/secure/index.htm"
;
}

Handles submission of the "add permission" form.

Handles submission of the add permission form .


@RequestMapping(value = "/secure/deletePermission.htm")
	public ModelAndView deletePermission(@RequestParam("contactId") long contactId,
			@RequestParam("sid") String sid, @RequestParam("permission") int mask) {

		Contact contact = contactManager.getById(contactId);

		Sid sidObject = new PrincipalSid(sid);
		Permission permission = permissionFactory.buildFromMask(mask);

		contactManager.deletePermission(contact, sidObject, permission);

		Map<String, Object> model = new HashMap<>();
		model.put("contact", contact);
		model.put("sid", sidObject);
		model.put("permission", permission);

		return new ModelAndView("deletePermission", "model", model);
	}

@ RequestMapping ( value = "/secure/deletePermission.htm" ) public ModelAndView deletePermission ( @ RequestParam ( "contactId" ) long contactId , @ RequestParam ( "sid" ) String sid , @ RequestParam ( "permission" ) int mask ) { Contact contact = contactManager . getById ( contactId ) ; Sid sidObject = new PrincipalSid ( sid ) ; Permission permission = permissionFactory . buildFromMask ( mask ) ; contactManager . deletePermission ( contact , sidObject , permission ) ; Map < String , Object > model = new HashMap <> ( ) ; model . put ( "contact" , contact ) ; model . put ( "sid" , sidObject ) ; model . put ( "permission" , permission ) ; return new ModelAndView ( "deletePermission" , "model" , model ) ; }


private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) {
		if (role == null) {
			return role;
		}
		if (defaultRolePrefix == null || defaultRolePrefix.length() == 0) {
			return role;
		}
		if (role.startsWith(defaultRolePrefix)) {
			return role;
		}
		return defaultRolePrefix + role;
	}

private static String getRoleWithDefaultPrefix ( String defaultRolePrefix , String role ) { if ( role == null ) { return role ; } if ( defaultRolePrefix == null || defaultRolePrefix . length ( ) == 0 ) { return role ; } if ( role . startsWith ( defaultRolePrefix ) ) { return role ; } return defaultRolePrefix + role ; }

Prefixes role with defaultRolePrefix if defaultRolePrefix is non-null and if role
does not already start with defaultRolePrefix.

@param defaultRolePrefix
@param role
@return

Prefixes role with defaultRolePrefix if defaultRolePrefix is non - null and if role does not already start with defaultRolePrefix .


public static UserDetailsResourceFactoryBean fromString(String users) {
		InMemoryResource resource = new InMemoryResource(users);
		return fromResource(resource);
	}

public static UserDetailsResourceFactoryBean fromString ( String users ) { InMemoryResource resource = new InMemoryResource ( users ) ; return fromResource ( resource ) ; }

Creates a UserDetailsResourceFactoryBean with a resource from the provided String

@param users the string representing the users
@return the UserDetailsResourceFactoryBean


public List<String> getAttributeValues(String name) {
		List<String> result = null;
		if (attributes != null) {
			result = attributes.get(name);
		}
		if (result == null) {
			result = Collections.emptyList();
		}
		return result;
	}

public List < String > getAttributeValues ( String name ) { List < String > result = null ; if ( attributes != null ) { result = attributes . get ( name ) ; } if ( result == null ) { result = Collections . emptyList ( ) ; } return result ; }

Returns the values for a specific attribute

@param name the attribute name
@return a String array, never null but may be zero length


public String getFirstAttributeValue(String name) {
		List<String> result = getAttributeValues(name);
		if (result.isEmpty()) {
			return null;
		}
		else {
			return result.get(0);
		}
	}

public String getFirstAttributeValue ( String name ) { List < String > result = getAttributeValues ( name ) ; if ( result . isEmpty ( ) ) { return null ; } else { return result . get ( 0 ) ; } }

Returns the first attribute value for a specified attribute

@param name
@return the first attribute value for a specified attribute, may be null


public static byte[] encode(CharSequence string) {
		try {
			ByteBuffer bytes = CHARSET.newEncoder().encode(CharBuffer.wrap(string));
			byte[] bytesCopy = new byte[bytes.limit()];
			System.arraycopy(bytes.array(), 0, bytesCopy, 0, bytes.limit());

			return bytesCopy;
		}
		catch (CharacterCodingException e) {
			throw new IllegalArgumentException("Encoding failed", e);
		}
	}

public
static
byte
[
]
encode
(
CharSequence
string
)
{
try
{
ByteBuffer
bytes
=
CHARSET
.
newEncoder
(
)
.
encode
(
CharBuffer
.
wrap
(
string
)
)
;
byte
[
]
bytesCopy
=
new
byte
[
bytes
.
limit
(
)
]
;
System
.
arraycopy
(
bytes
.
array
(
)
,
0
,
bytesCopy
,
0
,
bytes
.
limit
(
)
)
;
return
bytesCopy
;
}
catch
(
CharacterCodingException
e
)
{
throw
new
IllegalArgumentException
(
"Encoding failed"
,
e
)
;
}
}

Get the bytes of the String in UTF-8 encoded form.

Get the bytes of the String in UTF - 8 encoded form .


public static String decode(byte[] bytes) {
		try {
			return CHARSET.newDecoder().decode(ByteBuffer.wrap(bytes)).toString();
		}
		catch (CharacterCodingException e) {
			throw new IllegalArgumentException("Decoding failed", e);
		}
	}

public
static
String
decode
(
byte
[
]
bytes
)
{
try
{
return
CHARSET
.
newDecoder
(
)
.
decode
(
ByteBuffer
.
wrap
(
bytes
)
)
.
toString
(
)
;
}
catch
(
CharacterCodingException
e
)
{
throw
new
IllegalArgumentException
(
"Decoding failed"
,
e
)
;
}
}

Decode the bytes in UTF-8 form into a String.

Decode the bytes in UTF - 8 form into a String .


private <T extends AccessibleObject> String[] lookupParameterNames(
			ParameterNameFactory<T> parameterNameFactory, T t) {
		Annotation[][] parameterAnnotations = parameterNameFactory.findParameterAnnotations(t);
		int parameterCount = parameterAnnotations.length;
		String[] paramNames = new String[parameterCount];
		boolean found = false;
		for (int i = 0; i < parameterCount; i++) {
			Annotation[] annotations = parameterAnnotations[i];
			String parameterName = findParameterName(annotations);
			if (parameterName != null) {
				found = true;
				paramNames[i] = parameterName;
			}
		}
		return found ? paramNames : null;
	}

private < T extends AccessibleObject > String [ ] lookupParameterNames ( ParameterNameFactory < T > parameterNameFactory , T t ) { Annotation [ ] [ ] parameterAnnotations = parameterNameFactory . findParameterAnnotations ( t ) ; int parameterCount = parameterAnnotations . length ; String [ ] paramNames = new String [ parameterCount ] ; boolean found = false ; for ( int i = 0 ; i < parameterCount ; i ++ ) { Annotation [ ] annotations = parameterAnnotations [ i ] ; String parameterName = findParameterName ( annotations ) ; if ( parameterName != null ) { found = true ; paramNames [ i ] = parameterName ; } } return found ? paramNames : null ; }

Gets the parameter names or null if not found.

@param parameterNameFactory the {@link ParameterNameFactory} to use
@param t the {@link AccessibleObject} to find the parameter names on (i.e. Method
or Constructor)
@return the parameter names or null

Gets the parameter names or null if not found .


@RequestMapping(value = "/secure/add.htm", method = RequestMethod.POST)
	public String addContact(WebContact form, BindingResult result) {
		validator.validate(form, result);

		if (result.hasErrors()) {
			return "add";
		}

		Contact contact = new Contact(form.getName(), form.getEmail());
		contactManager.create(contact);

		return "redirect:/secure/index.htm";
	}

@ RequestMapping ( value = "/secure/add.htm" , method = RequestMethod . POST ) public String addContact ( WebContact form , BindingResult result ) { validator . validate ( form , result ) ; if ( result . hasErrors ( ) ) { return "add" ; } Contact contact = new Contact ( form . getName ( ) , form . getEmail ( ) ) ; contactManager . create ( contact ) ; return "redirect:/secure/index.htm" ; }

Handles the submission of the contact form, creating a new instance if the username
and email are valid.

Handles the submission of the contact form creating a new instance if the username and email are valid .


@Override
	protected Collection<ConfigAttribute> findAttributes(Method method,
			Class<?> targetClass) {
		if (targetClass == null) {
			return null;
		}

		return findAttributesSpecifiedAgainst(method, targetClass);
	}

@ Override protected Collection < ConfigAttribute > findAttributes ( Method method , Class < ? > targetClass ) { if ( targetClass == null ) { return null ; } return findAttributesSpecifiedAgainst ( method , targetClass ) ; }

Will walk the method inheritance tree to find the most specific declaration
applicable.

Will walk the method inheritance tree to find the most specific declaration applicable .


private void addSecureMethod(RegisteredMethod method, List<ConfigAttribute> attr) {
		Assert.notNull(method, "RegisteredMethod required");
		Assert.notNull(attr, "Configuration attribute required");
		if (logger.isInfoEnabled()) {
			logger.info("Adding secure method [" + method + "] with attributes [" + attr
					+ "]");
		}
		this.methodMap.put(method, attr);
	}

private
void
addSecureMethod
(
RegisteredMethod
method
,
List
<
ConfigAttribute
>
attr
)
{
Assert
.
notNull
(
method
,
"RegisteredMethod required"
)
;
Assert
.
notNull
(
attr
,
"Configuration attribute required"
)
;
if
(
logger
.
isInfoEnabled
(
)
)
{
logger
.
info
(
"Adding secure method ["
+
method
+
"] with attributes ["
+
attr
+
"]"
)
;
}
this
.
methodMap
.
put
(
method
,
attr
)
;
}

Add configuration attributes for a secure method.

@param method the method to be secured
@param attr required authorities associated with the method

Add configuration attributes for a secure method .


@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> allAttributes = new HashSet<>();

		for (List<ConfigAttribute> attributeList : methodMap.values()) {
			allAttributes.addAll(attributeList);
		}

		return allAttributes;
	}

@ Override public Collection < ConfigAttribute > getAllConfigAttributes ( ) { Set < ConfigAttribute > allAttributes = new HashSet <> ( ) ; for ( List < ConfigAttribute > attributeList : methodMap . values ( ) ) { allAttributes . addAll ( attributeList ) ; } return allAttributes ; }

Obtains the configuration attributes explicitly defined against this bean.

@return the attributes explicitly defined against this bean

Obtains the configuration attributes explicitly defined against this bean .


private boolean isMatch(String methodName, String mappedName) {
		return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0,
				mappedName.length() - 1)))
				|| (mappedName.startsWith("*") && methodName.endsWith(mappedName
						.substring(1, mappedName.length())));
	}

private boolean isMatch ( String methodName , String mappedName ) { return ( mappedName . endsWith ( "*" ) && methodName . startsWith ( mappedName . substring ( 0 , mappedName . length ( ) - 1 ) ) ) || ( mappedName . startsWith ( "*" ) && methodName . endsWith ( mappedName . substring ( 1 , mappedName . length ( ) ) ) ) ; }

Return if the given method name matches the mapped name. The default implementation
checks for "xxx" and "xxx" matches.

@param methodName the method name of the class
@param mappedName the name in the descriptor

@return if the names match

Return if the given method name matches the mapped name . The default implementation checks for xxx and xxx matches .


public C anyRequest() {
		Assert.state(!this.anyRequestConfigured, "Can't configure anyRequest after itself");
		C configurer = requestMatchers(ANY_REQUEST);
		this.anyRequestConfigured = true;
		return configurer;
	}

Maps any request.

@return the object that is chained after creating the {@link RequestMatcher}


protected void handleBindException(String userDn, String username, Throwable cause) {
		if (logger.isDebugEnabled()) {
			logger.debug("Failed to bind as " + userDn + ": " + cause);
		}
	}

protected
void
handleBindException
(
String
userDn
,
String
username
,
Throwable
cause
)
{
if
(
logger
.
isDebugEnabled
(
)
)
{
logger
.
debug
(
"Failed to bind as "
+
userDn
+
": "
+
cause
)
;
}
}

Allows subclasses to inspect the exception thrown by an attempt to bind with a
particular DN. The default implementation just reports the failure to the debug
logger.

Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN . The default implementation just reports the failure to the debug logger .


@Transactional(readOnly = true)
	public Contact getRandomContact() {
		logger.debug("Returning random contact");

		Random rnd = new Random();
		List<Contact> contacts = contactDao.findAll();
		int getNumber = rnd.nextInt(contacts.size());

		return contacts.get(getNumber);
	}

@
Transactional
(
readOnly
=
true
)
public
Contact
getRandomContact
(
)
{
logger
.
debug
(
"Returning random contact"
)
;
Random
rnd
=
new
Random
(
)
;
List
<
Contact
>
contacts
=
contactDao
.
findAll
(
)
;
int
getNumber
=
rnd
.
nextInt
(
contacts
.
size
(
)
)
;
return
contacts
.
get
(
getNumber
)
;
}


protected final void clearAuthenticationAttributes(HttpServletRequest request) {
		HttpSession session = request.getSession(false);

		if (session == null) {
			return;
		}

		session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
	}

protected final void clearAuthenticationAttributes ( HttpServletRequest request ) { HttpSession session = request . getSession ( false ) ; if ( session == null ) { return ; } session . removeAttribute ( WebAttributes . AUTHENTICATION_EXCEPTION ) ; }

Removes temporary authentication-related data which may have been stored in the
session during the authentication process.

Removes temporary authentication - related data which may have been stored in the session during the authentication process .


public static Field getField(Class<?> clazz, String fieldName)
			throws IllegalStateException {
		Assert.notNull(clazz, "Class required");
		Assert.hasText(fieldName, "Field name required");

		try {
			return clazz.getDeclaredField(fieldName);
		}
		catch (NoSuchFieldException nsf) {
			// Try superclass
			if (clazz.getSuperclass() != null) {
				return getField(clazz.getSuperclass(), fieldName);
			}

			throw new IllegalStateException("Could not locate field '" + fieldName
					+ "' on class " + clazz);
		}
	}

public
static
Field
getField
(
Class
<
>
clazz
,
String
fieldName
)
throws
IllegalStateException
{
Assert
.
notNull
(
clazz
,
"Class required"
)
;
Assert
.
hasText
(
fieldName
,
"Field name required"
)
;
try
{
return
clazz
.
getDeclaredField
(
fieldName
)
;
}
catch
(
NoSuchFieldException
nsf
)
{
// Try superclass
if
(
clazz
.
getSuperclass
(
)
!=
)
{
return
getField
(
clazz
.
getSuperclass
(
)
,
fieldName
)
;
}
throw
new
IllegalStateException
(
"Could not locate field '"
+
fieldName
+
"' on class "
+
clazz
)
;
}
}

Attempts to locate the specified field on the class.

@param clazz the class definition containing the field
@param fieldName the name of the field to locate

@return the Field (never null)

@throws IllegalStateException if field could not be found

Attempts to locate the specified field on the class .


protected String createServiceUrl(final HttpServletRequest request,
			final HttpServletResponse response) {
		return CommonUtils.constructServiceUrl(null, response,
				this.serviceProperties.getService(), null,
				this.serviceProperties.getArtifactParameter(),
				this.encodeServiceUrlWithSessionId);
	}

protected String createServiceUrl ( final HttpServletRequest request , final HttpServletResponse response ) { return CommonUtils . constructServiceUrl ( null , response , this . serviceProperties . getService ( ) , null , this . serviceProperties . getArtifactParameter ( ) , this . encodeServiceUrlWithSessionId ) ; }

Constructs a new Service Url. The default implementation relies on the CAS client
to do the bulk of the work.
@param request the HttpServletRequest
@param response the HttpServlet Response
@return the constructed service url. CANNOT be NULL.

Constructs a new Service Url . The default implementation relies on the CAS client to do the bulk of the work .


protected String createRedirectUrl(final String serviceUrl) {
		return CommonUtils.constructRedirectUrl(this.loginUrl,
				this.serviceProperties.getServiceParameter(), serviceUrl,
				this.serviceProperties.isSendRenew(), false);
	}

protected String createRedirectUrl ( final String serviceUrl ) { return CommonUtils . constructRedirectUrl ( this . loginUrl , this . serviceProperties . getServiceParameter ( ) , serviceUrl , this . serviceProperties . isSendRenew ( ) , false ) ; }

Constructs the Url for Redirection to the CAS server. Default implementation relies
on the CAS client to do the bulk of the work.

@param serviceUrl the service url that should be included.
@return the redirect url. CANNOT be NULL.

Constructs the Url for Redirection to the CAS server . Default implementation relies on the CAS client to do the bulk of the work .


private String extractPrefix(String encPass) {
		if (!encPass.startsWith("{")) {
			return null;
		}

		int secondBrace = encPass.lastIndexOf('}');

		if (secondBrace < 0) {
			throw new IllegalArgumentException(
					"Couldn't find closing brace for SHA prefix");
		}

		return encPass.substring(0, secondBrace + 1);
	}

Returns the hash prefix or null if there isn't one.

Returns the hash prefix or null if there isn t one .


public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException arg2) throws IOException, ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Pre-authenticated entry point called. Rejecting access");
		}
		response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
	}

Always returns a 403 error code to the client.

Always returns a 403 error code to the client .


private void checkFilterStack(List<Filter> filters) {
		checkForDuplicates(SecurityContextPersistenceFilter.class, filters);
		checkForDuplicates(UsernamePasswordAuthenticationFilter.class, filters);
		checkForDuplicates(SessionManagementFilter.class, filters);
		checkForDuplicates(BasicAuthenticationFilter.class, filters);
		checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters);
		checkForDuplicates(JaasApiIntegrationFilter.class, filters);
		checkForDuplicates(ExceptionTranslationFilter.class, filters);
		checkForDuplicates(FilterSecurityInterceptor.class, filters);
	}

private void checkFilterStack ( List < Filter > filters ) { checkForDuplicates ( SecurityContextPersistenceFilter . class , filters ) ; checkForDuplicates ( UsernamePasswordAuthenticationFilter . class , filters ) ; checkForDuplicates ( SessionManagementFilter . class , filters ) ; checkForDuplicates ( BasicAuthenticationFilter . class , filters ) ; checkForDuplicates ( SecurityContextHolderAwareRequestFilter . class , filters ) ; checkForDuplicates ( JaasApiIntegrationFilter . class , filters ) ; checkForDuplicates ( ExceptionTranslationFilter . class , filters ) ; checkForDuplicates ( FilterSecurityInterceptor . class , filters ) ; }

Checks the filter list for possible errors and logs them


@SuppressWarnings("unchecked")
	final Class<? extends Throwable>[] getRegisteredTypes() {
		Set<Class<? extends Throwable>> typeList = this.extractorMap.keySet();
		return typeList.toArray(new Class[typeList.size()]);
	}

@ SuppressWarnings ( "unchecked" ) final Class < ? extends Throwable > [ ] getRegisteredTypes ( ) { Set < Class < ? extends Throwable > > typeList = this . extractorMap . keySet ( ) ; return typeList . toArray ( new Class [ typeList . size ( ) ] ) ; }

Returns an array containing the classes for which extractors are registered. The
order of the classes is the order in which comparisons will occur for resolving a
matching extractor.

@return the types for which extractors are registered

Returns an array containing the classes for which extractors are registered . The order of the classes is the order in which comparisons will occur for resolving a matching extractor .


private Throwable extractCause(Throwable throwable) {
		for (Map.Entry<Class<? extends Throwable>, ThrowableCauseExtractor> entry : extractorMap
				.entrySet()) {
			Class<? extends Throwable> throwableType = entry.getKey();
			if (throwableType.isInstance(throwable)) {
				ThrowableCauseExtractor extractor = entry.getValue();
				return extractor.extractCause(throwable);
			}
		}

		return null;
	}

private Throwable extractCause ( Throwable throwable ) { for ( Map . Entry < Class < ? extends Throwable > , ThrowableCauseExtractor > entry : extractorMap . entrySet ( ) ) { Class < ? extends Throwable > throwableType = entry . getKey ( ) ; if ( throwableType . isInstance ( throwable ) ) { ThrowableCauseExtractor extractor = entry . getValue ( ) ; return extractor . extractCause ( throwable ) ; } } return null ; }

Extracts the cause of the given throwable using an appropriate extractor.

@param throwable the Throwable (not null
@return the cause, may be null if none could be resolved

Extracts the cause of the given throwable using an appropriate extractor .


@SuppressWarnings({ "unchecked", "rawtypes" })
	private String registerAccessManager(ParserContext pc, boolean jsr250Enabled,
			BeanDefinition expressionVoter) {

		BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder
				.rootBeanDefinition(AffirmativeBased.class);
		ManagedList voters = new ManagedList(4);

		if (expressionVoter != null) {
			voters.add(expressionVoter);
		}
		voters.add(new RootBeanDefinition(RoleVoter.class));
		voters.add(new RootBeanDefinition(AuthenticatedVoter.class));

		if (jsr250Enabled) {
			voters.add(new RootBeanDefinition(Jsr250Voter.class));
		}

		accessMgrBuilder.addConstructorArgValue(voters);

		BeanDefinition accessManager = accessMgrBuilder.getBeanDefinition();
		String id = pc.getReaderContext().generateBeanName(accessManager);
		pc.registerBeanComponent(new BeanComponentDefinition(accessManager, id));

		return id;
	}

@ SuppressWarnings ( { "unchecked" , "rawtypes" } ) private String registerAccessManager ( ParserContext pc , boolean jsr250Enabled , BeanDefinition expressionVoter ) { BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder . rootBeanDefinition ( AffirmativeBased . class ) ; ManagedList voters = new ManagedList ( 4 ) ; if ( expressionVoter != null ) { voters . add ( expressionVoter ) ; } voters . add ( new RootBeanDefinition ( RoleVoter . class ) ) ; voters . add ( new RootBeanDefinition ( AuthenticatedVoter . class ) ) ; if ( jsr250Enabled ) { voters . add ( new RootBeanDefinition ( Jsr250Voter . class ) ) ; } accessMgrBuilder . addConstructorArgValue ( voters ) ; BeanDefinition accessManager = accessMgrBuilder . getBeanDefinition ( ) ; String id = pc . getReaderContext ( ) . generateBeanName ( accessManager ) ; pc . registerBeanComponent ( new BeanComponentDefinition ( accessManager , id ) ) ; return id ; }

Register the default AccessDecisionManager. Adds the special JSR 250 voter jsr-250
is enabled and an expression voter if expression-based access control is enabled.
@return

Register the default AccessDecisionManager . Adds the special JSR 250 voter jsr - 250 is enabled and an expression voter if expression - based access control is enabled .


public static Set<String> authorityListToSet(
			Collection<? extends GrantedAuthority> userAuthorities) {
		Assert.notNull(userAuthorities, "userAuthorities cannot be null");
		Set<String> set = new HashSet<>(userAuthorities.size());

		for (GrantedAuthority authority : userAuthorities) {
			set.add(authority.getAuthority());
		}

		return set;
	}

public
static
Set
<
String
>
authorityListToSet
(
Collection
<
extends
GrantedAuthority
>
userAuthorities
)
{
Assert
.
notNull
(
userAuthorities
,
"userAuthorities cannot be null"
)
;
Set
<
String
>
set
=
new
HashSet
<>
(
userAuthorities
.
size
(
)
)
;
for
(
GrantedAuthority
authority
:
userAuthorities
)
{
set
.
add
(
authority
.
getAuthority
(
)
)
;
}
return
set
;
}

Converts an array of GrantedAuthority objects to a Set.
@return a Set of the Strings obtained from each call to
GrantedAuthority.getAuthority()

Converts an array of GrantedAuthority objects to a Set .


private boolean matches(byte[] expected, byte[] actual) {
		if (expected.length != actual.length) {
			return false;
		}

		int result = 0;
		for (int i = 0; i < expected.length; i++) {
			result |= expected[i] ^ actual[i];
		}
		return result == 0;
	}

private boolean matches ( byte [ ] expected , byte [ ] actual ) { if ( expected . length != actual . length ) { return false ; } int result = 0 ; for ( int i = 0 ; i < expected . length ; i ++ ) { result |= expected [ i ] ^ actual [ i ] ; } return result == 0 ; }

Constant time comparison to prevent against timing attacks.

Constant time comparison to prevent against timing attacks .