WebSphere 上的 Spring Security PreAuthentication Filter 示例?
Posted
技术标签:
【中文标题】WebSphere 上的 Spring Security PreAuthentication Filter 示例?【英文标题】:Example of Spring Security PreAuthentication Filter on WebSphere? 【发布时间】:2012-12-14 01:20:20 【问题描述】:是否有人有用于 WebSphere 工作的 Spring Security 示例 PreAuthentication Filter (WebSpherePreAuthenticatedProcessingFilter)?关于它的文档很少,我似乎无法确定它。我正在寻找可以使用它并且可能愿意提供您的配置示例的人。非常适合 Spring 3.1 和 WAS 7 或 8。
我有一个看起来“有点”工作的配置。我可以通过 WebSphere 进行身份验证,然后在我的应用程序中点击一个 URL,但浏览器返回此消息:
错误 500:java.lang.RuntimeException:为用户查找组时发生异常
我得到这样的异常堆栈跟踪:
java.lang.RuntimeException: Error while invoking method java.lang.reflect.Method.getGroupsForUser([UNAUTHENTICATED])
at org.springframework.security.web.authentication.preauth.websphere.DefaultWASUsernameAndGroupsExtractor.invokeMethod(DefaultWASUsernameAndGroupsExtractor.java:147) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.preauth.websphere.DefaultWASUsernameAndGroupsExtractor.getWebSphereGroups(DefaultWASUsernameAndGroupsExtractor.java:115) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.preauth.websphere.DefaultWASUsernameAndGroupsExtractor.getWebSphereGroups(
...
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60) ~[na:1.6.0]
...
Caused by: com.ibm.websphere.security.EntryNotFoundException: null
at com.ibm.ws.wim.registry.util.MembershipBridge.getGroupsForUser(MembershipBridge.java:293) ~[com.ibm.ws.runtime.wim.core.jar:201207200704]
...
[12/28/12 14:05:15:879 CST] 00000055 LocalTranCoor E WLTC0017E: Resources rolled back due to setRollbackOnly() being called.
[12/28/12 14:05:15:879 CST] 00000055 webapp E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet Error]-[ServletNameNotFound]: java.lang.RuntimeException: Exception occured while looking up groups for user
at org.springframework.security.web.authentication.preauth.websphere.DefaultWASUsernameAndGroupsExtractor.getWebSphereGroups(DefaultWASUsernameAndGroupsExtractor.java:123)
at org.springframework.security.web.authentication.preauth.websphere.DefaultWASUsernameAndGroupsExtractor.getWebSphereGroups(DefaultWASUsernameAndGroupsExtractor.java:94)
...
我的web.xml文件如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext-jcr.xml,
classpath*:/applicationContext-security.xml
</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!--
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
-->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- ====================================================================== -->
<!-- S E R V L E T S -->
<!-- ====================================================================== -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>ViewStatusMessages</servlet-name>
<servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
</servlet>
<!-- ====================================================================== -->
<!-- S E R V L E T M A P P I N G S -->
<!-- ====================================================================== -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ViewStatusMessages</servlet-name>
<url-pattern>/lbClassicStatus</url-pattern>
</servlet-mapping>
<!-- ====================================================================== -->
<!-- W E L C O M E F I L E S -->
<!-- ====================================================================== -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Use if configuring for JNDI Datasource on J2EE Server -->
<resource-ref id="ResourceRef_LDP_Datasource">
<description>Resource reference to the LDP datasource.</description>
<!-- DB2 -->
<res-ref-name>jdbc/ldpdbDS</res-ref-name>
<!-- MS SQL -->
<!--
<res-ref-name>jdbc/ldpdbMSSQLDS</res-ref-name>
-->
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<!--
security-constraint reference:
http://s170.codeinspot.com/q/3419721
OK, I figured this out. The problem is that even though I had J2EE security setup in Websphere and was authenticated,
my web.xml contained no security constraints. Because of this, Websphere was not supplying the principal for my requests.
This is apparently an intentional feature. If you are not accessing a protected URL, you should not need the pre-authentication information.
To overcome this, I added a security constraint to my web.xml, which allowed ALL users to access the resources.
Effectively, the resources were not secured, but still - there was a constraint now.
This tricks the Websphere into filling in the user principal information in the request.
-->
<security-constraint>
<web-resource-collection>
<web-resource-name>All areas</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
我的 Spring 安全上下文 XML 文件如下:
<!--
<sec:http use-expressions="true">
<sec:intercept-url pattern="/**" access="denyAll" />
<sec:form-login />
</sec:http>
-->
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<!--
<sec:filter-chain pattern="/**" filters="sif,webspherePreAuthFilter,logoutFilter,etf,fsi"/>
-->
<sec:filter-chain pattern="/**" filters="webspherePreAuthFilter,logoutFilter,etf,fsi"/>
</sec:filter-chain-map>
</bean>
<!--
<bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
<bean id="sif" class="org.springframework.security.web.context.SecurityContextIntegrationFilter"/>
-->
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="preAuthenticatedAuthenticationProvider"/>
</sec:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/>
</bean>
<bean id="preAuthenticatedUserDetailsService" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/>
<!--
This AbstractPreAuthenticatedProcessingFilter implementation is based on WebSphere authentication.
It will use the WebSphere RunAs user principal name as the pre-authenticated principal.
-->
<bean id="webspherePreAuthFilter" class="org.springframework.security.web.authentication.preauth.websphere.WebSpherePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationDetailsSource" ref="authenticationDetailsSource"/>
</bean>
<bean id="preAuthenticatedProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<!--
This AuthenticationDetailsSource implementation will set the pre-authenticated granted authorities based on the WebSphere
groups for the current WebSphere user, mapped using the configured Attributes2GrantedAuthoritiesMapper.
This AuthenticationDetailsSource implementation, when configured with a MutableGrantedAuthoritiesContainer,
will set the pre-authenticated granted authorities based on the WebSphere groups for the current WebSphere user,
mapped using the configured Attributes2GrantedAuthoritiesMapper.
By default, this class is configured to build instances of the PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails class.
-->
<bean id="authenticationDetailsSource" class="org.springframework.security.web.authentication.preauth.websphere.WebSpherePreAuthenticatedWebAuthenticationDetailsSource">
<property name="webSphereGroups2GrantedAuthoritiesMapper" ref="websphereUserGroups2GrantedAuthoritiesMapper"/>
</bean>
<bean id="websphereUserGroups2GrantedAuthoritiesMapper" class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
<property name="convertAttributeToUpperCase" value="true"/>
</bean>
<bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
<constructor-arg ref="servletContext"/>
<constructor-arg value="/WEB-INF/web.xml"/>
</bean>
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
<bean id="etf" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="preAuthenticatedProcessingFilterEntryPoint"/>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
<!-- See: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-web-filters.html -->
<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadataSource">
<sec:filter-security-metadata-source>
<sec:intercept-url pattern="/**" access="ROLE_LDP_ADMINS"/>
</sec:filter-security-metadata-source>
</property>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<!--
Simply put, the filter wraps the current httprequest with one that delegates request.isUserInRole() and request.getRemoteUser() to acegi.
<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter">
<property name="wrapperClass" value="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper"/>
</bean>
-->
【问题讨论】:
您的 xml 块已损坏:例如,</web-app>
未显示在呈现的输出中,并且您根本没有 <web-app>
元素。
看到完整的堆栈跟踪会很有趣,而不仅仅是第一行。
【参考方案1】:
我没有可用的配置,但有一条建议
启用 Spring Security 调试日志记录 尽可能地调试到MembershipBridge.getGroupsForUser
,我感觉传递给它的用户名是空的
根据我的直觉,我怀疑预认证用户的名称没有被传递。我模糊地记得几年前我有这个 - 需要挖掘那个代码。
【讨论】:
【参考方案2】:由于某种原因,WebSphere 不需要对具有以下约束定义的资源进行身份验证,并且不会发生预身份验证:
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
在后期尝试为未知主体确定组时失败。
我使用默认组 Users 保护资源并将所有用户映射到它:
<security-constraint>
<web-resource-collection>
<web-resource-name>AuthTest</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>User</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>User</role-name>
</security-role>
这是一种解决方法,因为我不想要这个角色并管理它的成员,但这是我现在所拥有的。
【讨论】:
以上是关于WebSphere 上的 Spring Security PreAuthentication Filter 示例?的主要内容,如果未能解决你的问题,请参考以下文章
在Websphere Application Server上的应用程序启动时未调用MDB的ejbCreate()方法
Struts/Spring WebSphere jndi 错误
为啥我们的 Spring/Hibernate/JDBC/Websphere 系统中的连接过早关闭?
当会话在 websphere 中失效时,Spring 视图范围不会被破坏