我正在使用这个环境:
在我的环境中,我有一个SSO系统,我需要在这个系统中集成我的web应用程序。这个系统是私人产品。SSO机制的最终结果是在请求头中放置一个参数。所以我在申请中应该做的是:
此场景类似于CAS集成场景;所以我从CAS集成着手;我写了我的自定义过滤器,我写了我的自定义入口点和处理请求所需的所有其他类,但我面临一些问题;现在我可以在spring上下文中进行身份验证,但是在经过身份验证之后,就像没有经过身份验证一样。也许我漏掉了什么。
我将报告所有涉及的类和安全上下文。
security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!-- Nessuna sicurezza per avere i CSS e JS -->
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/DataTables-1.9.4/**" security="none"/>
<security:http pattern="/images/**" security="none"/>
<security:http pattern="/jquery-ui-1.10.3/**" security="none"/>
<security:http pattern="/json/**" security="none"/>
<security:http pattern="/jstree-v.pre1.0/**" security="none"/>
<security:http pattern="/ol213/**" security="none"/>
<security:http pattern="/sld/**" security="none"/>
<!-- Configurazione sicurezza -->
<security:http use-expressions="true" disable-url-rewriting="true"
entry-point-ref="webSealEntryPoint" request-matcher-ref="webSealReqMatcher">
<security:custom-filter ref="webSealAuthFilter" position="FIRST"/>
<security:intercept-url pattern="/comiajax/pages/*" access="hasAnyRole('OMNIA_ADMIN','DOMAIN_ADMIN','OMNIA_GUEST', 'DOMAIN_GUEST')"/>
<security:session-management>
<security:concurrency-control error-if-maximum-exceeded="true" max-sessions="1"/>
</security:session-management>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="webSealAuthProvider" />
</security:authentication-manager>
<bean id="webSealAuthFilter" class="it.angelo.spring.web.security.auth.filter.WebSealAuthenticationFilter">
<constructor-arg ref="webSealReqMatcher"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationDetailsSource">
<bean class="it.angelo.spring.web.security.auth.ServiceAuthenticationDetailsSource"/>
</property>
</bean>
<bean id="webSealEntryPoint" class="it.angelo.spring.web.security.entrypoint.WebSealEntryPoint">
<property name="usernameHeaderParam" value="iv-user" />
</bean>
<bean id="webSealAuthProvider" class="it.angelo.spring.web.security.auth.providers.WcmSealAuthProvider">
<property name="authenticationUserDetailsService" ref="wcmSecurityUserSvc"/>
</bean>
<security:user-service id="userService">
<security:user name="angelo" password="angelo" authorities="OMNIA_ADMIN,"/>
<security:user name="gina" password="gina" authorities="DOMAIN_ADMIN"/>
<security:user name="costa" password="costa" authorities="OMNIA_GUEST"/>
<security:user name="marianna" password="marianna" authorities="DOMAIN_GUEST"/>
</security:user-service>
<bean id="webSealReqMatcher" class="it.angelo.spring.web.security.auth.requestmatchers.WebSealRequestMatcher"/>
<bean id="wcmSecurityUserSvc" class="it.angelo.spring.web.security.userdetails.GrantedFromIvUsernameAttributesUserDetailsService"/>
</beans>
我的自定义筛选器
public class WebSealAuthenticationFilter extends AbstractAuthenticationProcessingFilter
{
protected WebSealAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher)
{
super(requiresAuthenticationRequestMatcher);
}
private static final Log logger = LogFactory.getLog(WebSealAuthenticationFilter.class.getName());
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException
{
WebSealIvUserNameAuthenticationToken auth = new WebSealIvUserNameAuthenticationToken(request.getHeader(WebSealRequestMatcher.DEFAULT_HEADER_PARAM));
auth.setDetails(this.authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(auth);
}
@Override
protected final void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException
{
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
// Propaga l'evento
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
request.getSession().setAttribute("autenticato", new Boolean(true));
chain.doFilter(request, response);
}
}
我的请求匹配器(我知道我可以使用org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher类,以后我将使用它)
public class WebSealRequestMatcher implements RequestMatcher
{
public static final String DEFAULT_HEADER_PARAM = "iv-user";
@Override
public boolean matches(HttpServletRequest request)
{
String headerParam = request.getHeader(DEFAULT_HEADER_PARAM);
return !StringUtils.hasText(headerParam);
}
}
我的AuthenticationProvider
public class WcmSealAuthProvider implements AuthenticationProvider
{
private static final Log logger = LogFactory.getLog(WcmSealAuthProvider.class.getName());
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
private AuthenticationUserDetailsService<WebSealIvUserNameAuthenticationToken> authenticationUserDetailsService;
public void setAuthenticationUserDetailsService(final AuthenticationUserDetailsService<WebSealIvUserNameAuthenticationToken> svc)
{
this.authenticationUserDetailsService = svc;
}
public AuthenticationUserDetailsService<WebSealIvUserNameAuthenticationToken> getAuthenticationUserDetailsService()
{
return authenticationUserDetailsService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
if( !supports(authentication.getClass()) )
{
if( logger.isInfoEnabled() )
{
logger.info("Classe "+authentication.getClass().getName()+" non supportata");
}
return null;
}
if( authentication instanceof WebSealIvUserNameAuthenticationToken )
{
return doAuthenticationNow(authentication);
}
return null;
}
@Override
public boolean supports(Class<?> authentication)
{
return WebSealIvUserNameAuthenticationToken.class.isAssignableFrom(authentication);
}
private WebSealAuthenticationToken doAuthenticationNow(final Authentication authentication)
{
try {
final String ivUserName = ((WebSealIvUserNameAuthenticationToken)authentication).getIvUserName();
UserDetails userDetails = loadUserByIvUserName(ivUserName);
return new WebSealAuthenticationToken(userDetails, userDetails.getAuthorities(),
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, userDetails.getUsername());
} catch (final Exception e) {
throw new BadCredentialsException(e.getMessage(), e);
}
}
protected UserDetails loadUserByIvUserName( final String ivUserName )
{
return this.authenticationUserDetailsService.loadUserDetails(new WebSealIvUserNameAuthenticationToken(ivUserName));
}
}
我的身份验证令牌
public class WebSealIvUserNameAuthenticationToken extends AbstractAuthenticationToken implements Serializable
{
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private String ivUserName;
public WebSealIvUserNameAuthenticationToken(String ivUserName)
{
super(new ArrayList<GrantedAuthority>());
this.ivUserName = ivUserName;
}
@Override
public Object getCredentials()
{
return null;
}
@Override
public Object getPrincipal()
{
return null;
}
public String getIvUserName()
{
return ivUserName;
}
}
public final class WebSealAuthenticationToken extends AbstractAuthenticationToken implements Serializable
{
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object credentials;
private final Object principal;
private final UserDetails userDetails;
private String ivUserName;
public WebSealAuthenticationToken( final Object principal,
final Object credentials,
final Collection<? extends GrantedAuthority> authorities,
final UserDetails userDetails,
final String ivUserName)
{
super(authorities);
if (((principal == null) || "".equals(principal) || (credentials == null)
|| "".equals(credentials) || (authorities == null) || (userDetails == null)
|| !StringUtils.hasText(ivUserName))) {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}
this.principal = principal;
this.credentials = credentials;
this.userDetails = userDetails;
this.ivUserName = ivUserName;
setAuthenticated(true);
}
@Override
public Object getCredentials()
{
return this.credentials;
}
@Override
public Object getPrincipal()
{
return this.principal;
}
public UserDetails getUserDetails()
{
return userDetails;
}
public String getIvUserName()
{
return ivUserName;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
if (obj instanceof WebSealAuthenticationToken) {
WebSealAuthenticationToken test = (WebSealAuthenticationToken) obj;
if (!this.ivUserName.equals(test.getIvUserName())) {
return false;
}
return true;
}
return false;
}
}
My AuthenticationUserDetailsService
public abstract class AbstractUserDetailsService implements AuthenticationUserDetailsService<WebSealIvUserNameAuthenticationToken>
{
@Override
public UserDetails loadUserDetails(final WebSealIvUserNameAuthenticationToken token) throws UsernameNotFoundException
{
return loadUserDetails(token.getIvUserName());
}
protected abstract UserDetails loadUserDetails(String ivUserName);
}
public class GrantedFromIvUsernameAttributesUserDetailsService extends AbstractUserDetailsService
{
private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD";
@Override
protected UserDetails loadUserDetails(String ivUserName)
{
// TODO Inserire il codice per recuperare l'utente da PUMA
final List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
grantedAuthorities.add(new SimpleGrantedAuthority("OMNIA_ADMIN"));
grantedAuthorities.add(new SimpleGrantedAuthority("DOMAIN_ADMIN"));
grantedAuthorities.add(new SimpleGrantedAuthority("OMNIA_GUEST"));
grantedAuthorities.add(new SimpleGrantedAuthority("DOMAIN_GUEST"));
return new User("fromWebSeal", NON_EXISTENT_PASSWORD_VALUE, true, true, true, true, grantedAuthorities);
}
}
我的身份验证DetailsSource
public class ServiceAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, ServiceAuthenticationDetails>
{
@Override
public ServiceAuthenticationDetails buildDetails(HttpServletRequest request)
{
return new DefaultServiceAuthenticationDetails(request);
}
}
public class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails implements ServiceAuthenticationDetails
{
private static final long serialVersionUID = 6056034551086630421L;
private String ivUserName;
public DefaultServiceAuthenticationDetails(HttpServletRequest request)
{
super(request);
String headerParam = request.getHeader(WebSealRequestMatcher.DEFAULT_HEADER_PARAM);
this.ivUserName = StringUtils.hasText(headerParam) ? headerParam : "nonValorizzato"+System.nanoTime();
}
@Override
public String getIvUserName()
{
return ivUserName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ivUserName.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj) || !(obj instanceof DefaultServiceAuthenticationDetails)) {
return false;
}
ServiceAuthenticationDetails that = (ServiceAuthenticationDetails) obj;
return ivUserName.equals(that.getIvUserName());
}
}
public interface ServiceAuthenticationDetails extends Serializable
{
public String getIvUserName();
}
在我看来,这一切都是正确的;无论如何,当我试图访问页面http://myhost:myport/media/comiajax/pages/uploadmedia
时,我遇到了一个循环,页面无法加载....有人能帮我吗?
欢迎提供任何提示
谢谢。
安杰洛
我刚刚意识到我在代码中犯了一些错误:)并不是所有的代码都能很好地工作;首先,我以这种方式修改了入口点:
public class WebSealEntryPoint implements AuthenticationEntryPoint, InitializingBean
{
private String webSealUrl;
@Override
public void afterPropertiesSet() throws Exception
{
Assert.hasLength(this.webSealUrl, "Indicare l'URL del WebSeal");
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authExp) throws IOException, ServletException
{
String url = webSealUrl+"?service="+request.getRequestURL();
response.sendRedirect(url);
}
public String getWebSealUrl()
{
return webSealUrl;
}
public void setWebSealUrl(String webSealUrl)
{
this.webSealUrl = webSealUrl;
}
}
正如yuo所看到的,我添加了一个与CAS添加的重定向非常相似的重定向;然后我以这种方式修改了security-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<security:http use-expressions="true" disable-url-rewriting="true"
entry-point-ref="webSealEntryPoint" request-matcher-ref="webSealReqMatcher">
<security:intercept-url pattern="/css/**" access="permitAll"/>
<security:intercept-url pattern="/DataTables-1.9.4/**" access="permitAll"/>
<security:intercept-url pattern="/images/**" access="permitAll"/>
<security:intercept-url pattern="/jquery-ui-1.10.3/**" access="permitAll"/>
<security:intercept-url pattern="/json/**" access="permitAll"/>
<security:intercept-url pattern="/jstree-v.pre1.0/**" access="permitAll"/>
<security:intercept-url pattern="/ol213/**" access="permitAll"/>
<security:intercept-url pattern="/sld/**" access="permitAll"/>
<security:intercept-url pattern="/comiajax/pages/*" access="hasAnyRole('OMNIA_ADMIN','DOMAIN_ADMIN','OMNIA_GUEST', 'DOMAIN_GUEST')"/>
<security:session-management>
<security:concurrency-control error-if-maximum-exceeded="true" max-sessions="1"/>
</security:session-management>
<security:custom-filter ref="webSealAuthFilter" position="LAST"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="webSealAuthProvider" />
</security:authentication-manager>
<bean id="webSealAuthFilter" class="it.angelo.spring.web.security.auth.filter.WebSealAuthenticationFilter">
<constructor-arg ref="webSealReqMatcher"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationDetailsSource">
<bean class="it.angelo.spring.web.security.auth.ServiceAuthenticationDetailsSource"/>
</property>
</bean>
<bean id="webSealEntryPoint" class="it.angelo.spring.web.security.entrypoint.WebSealEntryPoint">
<property name="webSealUrl" value="http://localhost:8380/WebSeal" />
</bean>
<bean id="webSealAuthProvider" class="it.angelo.spring.web.security.auth.providers.WcmSealAuthProvider">
<property name="authenticationUserDetailsService" ref="wcmSecurityUserSvc"/>
</bean>
<security:user-service id="userService">
<security:user name="angelo" password="angelo" authorities="OMNIA_ADMIN,"/>
<security:user name="gina" password="gina" authorities="DOMAIN_ADMIN"/>
<security:user name="costa" password="costa" authorities="OMNIA_GUEST"/>
<security:user name="marianna" password="marianna" authorities="DOMAIN_GUEST"/>
</security:user-service>
<bean id="webSealReqMatcher" class="it.angelo.spring.web.security.auth.requestmatchers.WebSealRequestMatcher"/>
<bean id="wcmSecurityUserSvc" class="it.angelo.spring.web.security.userdetails.GrantedFromIvUsernameAttributesUserDetailsService"/>
</beans>
谢谢。
安杰洛
我有一个带有OAuth2授权和资源服务器的Spring引导设置。用户可以通过向发出POST请求来获取令牌。到目前为止,一切都很好。 但是,我不想通过基本auth保护,而是通过自定义安全过滤器。 一些简单的例子如何实现这一点将是非常有帮助的。谢谢!
如何在链顶部的Spring Security链中插入多个自定义过滤器? 我可以通过在="FIRST"之后使用和之后尝试多个
众所周知,WebSecurityConfigurerAdapter类已被弃用。 我试图在filterChain中实现customFilter,但我遇到了一个与新的AuthenticationManager相关的问题。 问题是这样的: 如您所见,身份验证管理器需要AuthenticationConfiguration类作为NotNull参数,没有它,我无法创建CustomAuthentication
我需要以这样的方式自定义我的身份验证过程: 客户端发送带有“特殊”URL参数的请求(RESTAPI) 我把我的服务器端(2 3)分成两部分——(2)的自定义过滤器,它获取用户名——和(3)的自定义,它通过在数据库中查找名称来构建主体。 但是我不能正确地构建我的-每次它似乎根本不处理过滤器。我认为问题出在第一个(超文本传输协议)节点,但我无法理解我应该为过滤器设置什么位置。这是我的配置: PS-请不
演示在网关追加一个header public class CustomFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 演示在网关追加heade
SOFARPC 提供了一套良好的可扩展性机制,为各个模块提供 SPI 的能力。 SOFARPC 对请求与响应的过滤链处理方式是通过多个过滤器 Filter 来进行具体的拦截处理,该部分可由用户自定义 Filter 扩展,自定义 Filter 的执行顺序在内置 Filter 之后。具体方式如下: Bolt Filter 新建自定义 Filter 。 public class CustomFilter