1

我是 spring security 的新手,似乎我有一个对我、常见问题解答和其他网站来说太难的问题。

任务是:

  1. 我有带有登录表单的 spring 应用程序。一切正常。

  2. 现在我需要能够从应用程序获取任何允许的页面,但通过 URL 进行身份验证......类似于:http://myapp.de?login=test&password=test。我用 PRE_AUTH_FILTER 做到了。一切都适用于 URL。

  3. 问题是我的应用程序中需要两种身份验证方式。假设如果 PRE_AUTH_FILTER 失败,则加载标准登录表单。所以: http: //myapp.de将显示我的登录表单和第 1 点)。

现在有了我的安全配置,我只有 PRE_AUTH_FILTER 工作。

我错过了什么?

<sec:http auto-config="true" use-expressions="true">
    <sec:form-login login-page="/login.jsp" default-target-url="/start" authentication-failure-url="/login.jsp?error=true"/>
    <sec:logout logout-url="/logout" logout-success-url="/login.jsp"/>
    <sec:anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/>
    <sec:access-denied-handler error-page="/error403.jsp"/>
    <sec:intercept-url pattern="/login*" access="permitAll"/>   
    <sec:intercept-url pattern="/objautocomplete*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/start*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/u*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/crosstable*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/objcen*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/objchecks*" access="hasRole('ROLE_USER')"/>
    <sec:intercept-url pattern="/globalcen*" access="hasRole('ROLE_USER')"/>
    <sec:custom-filter position="PRE_AUTH_FILTER" ref="preAuthFilter" />
    <sec:remember-me/>
</sec:http>

    <!-- PRE_ AUTHENTICATION -->        
<beans:bean id="userDetailsServiceImpl"
    class="com.grsnet.qvs.auth.UserDetailsServiceImpl" />

<beans:bean id="preAuthenticatedProcessingFilterEntryPoint"
    class="com.grsnet.qvs.auth.LinkForbiddenEntryPoint" />

<beans:bean id="preAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <beans:property name="preAuthenticatedUserDetailsService" ref="userDetailsServiceImpl" />
</beans:bean>

<beans:bean id="preAuthFilter"
    class="com.grsnet.qvs.auth.UrlParametersAuthenticationFilter">
    <beans:property name="authenticationManager" ref="appControlAuthenticationManager" />
</beans:bean>

<sec:authentication-manager alias="appControlAuthenticationManager">
    <sec:authentication-provider ref="preAuthenticationProvider" />
</sec:authentication-manager>

    <!-- LOGIN FORM AUTHENTICATION -->  

<sec:authentication-manager>
    <sec:authentication-provider user-service-ref="qvsUserDetailsService"/>
</sec:authentication-manager>

<beans:bean id="qvsUserDetailsService" class="com.grsnet.qvs.auth.QVSUserDetailsService"/>

</beans:beans>

更新UrlParametersAuthenticationFilter.java

public class UrlParametersAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {

    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        if (request.getParameterMap().size() == 2) {
            return true;
        }
        return false;
    }

    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        String[] credentials = new String[2];
        credentials[0] = request.getParameter("j_username");
        credentials[1] = request.getParameter("j_password");
        return credentials;
    }
}
4

1 回答 1

1
<sec:custom-filter before="FORM_LOGIN_FILTER" ref="preAuthFilter" />

编辑:

是的,过滤器是一团糟。您甚至查看过 AbstractPreAuthenticatedProcessingFilter 的 javadoc 或源代码吗?PreAuthentication 在外部系统已经完成身份验证时使用。例如,如果您使用容器提供的 Java EE 身份验证,或者您有一个可以进行身份​​验证的 Web 前端,例如 NTLM/kerberos 的 IIS 前端。

此外,您的实现不正确,getPreAuthenticatedPrincipal() 应该返回用户名,也就是 Principal,而 getPreAuthenticatedCredentials 应该返回密码,也就是 Credentials。但更重要的是, AbstractPreAuthenticatedProcessingFilter不做任何 authentication。从 Javadoc 的第一行开始:

Base class for processing filters that handle pre-authenticated authentication requests, where it is assumed that the principal has already been authenticated by an external system.

所以,废弃你的过滤器并使用标准的 UsernamePasswordAuthenticationFilter

<beans:bean id="urlParameterAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <beans:property name="usernameParameter" value="username" />
    <beans:property name="passwordParameter" value="password" />
    <beans:property name="postOnly" value="false" />
    <beans:property name="authenticationManager" ref="appControlAuthenticationManager" />
</beans:bean>

然后将您的自定义过滤器声明替换为

<sec:custom-filter before="FORM_LOGIN_FILTER" ref="urlParameterAuthFilter" />

免责声明:在 URL 中传递密码是一个非常非常糟糕的主意,您一开始就不应该这样做。它将出现在访问日志中,并引入了一大堆真正不必要的安全问题。

于 2012-08-29T10:21:13.673 回答