使用Spring 3.1保护两个网页的密码

时间:2014-01-23 22:07:11

标签: java spring jsp spring-mvc spring-security

我一直在寻找已经接近我的问题,但似乎无法找到我正在寻找的确切答案。我猜想我想要做的解决方案非常简单。

我有一个带有默认页面的网站(index.jsp)。从索引页面到管理页面(admin.jsp)有一个链接。这个页面已经被Spring密码保护了很长时间没有问题。这是我一直在使用的安全上下文文件:

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                    http://www.springframework.org/schema/security 
                    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <global-method-security pre-post-annotations="enabled" secured-annotations="enabled"/>     

    <http use-expressions="true">
        <intercept-url pattern="/admin.jsp" access="hasRole('administrator')" />
        <intercept-url pattern="/**" access="permitAll" />
        <form-login login-page="/login.jsp" default-target-url="/admin.jsp" />
        <logout />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="${admin.username}" password="${admin.password}" authorities="administrator" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>   

我现在也需要密码保护index.jsp。如果我复制元素的子元素(我创建了单独的login.jsp文件,不确定是否有必要),如下所示:

<http use-expressions="true">
        <intercept-url pattern="/index.jsp" access="hasRole('user')" />
        <form-login login-page="/indexLogin.jsp" default-target-url="/index.jsp" />
        <logout />

        <intercept-url pattern="/admin.jsp" access="hasRole('administrator')" />
        <form-login login-page="/adminLogin.jsp" default-target-url="/admin.jsp" />
        <logout />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="${admin.username}" password="${admin.password}" authorities="administrator" />
                <user name="${user.username}" password="${user.password}" authorities="user" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

然后index.jsp完全按预期密码保护。但是,如果我单击在新选项卡中打开admin.jsp页面的按钮,我会收到403 - 访问被拒绝错误。我假设这是因为它会自动尝试在管理页面上使用用户凭据。

然后我尝试创建两个单独的元素,每个元素都包含每个不同页面的元素:

<http use-expressions="true">
        <intercept-url pattern="/index.jsp" access="hasRole('user')" />
        <form-login login-page="/indexLogin.jsp" default-target-url="/index.jsp" />
        <logout />
    </http>

    <http use-expressions="true">
        <intercept-url pattern="/admin.jsp" access="hasRole('administrator')" />
        <form-login login-page="/adminLogin.jsp" default-target-url="/admin.jsp" />
        <logout />
    </http>

然后我收到错误声明:

java.lang.IllegalArgumentException:通用匹配模式('/ **')在过滤器链中的其他模式之前定义,导致它们被忽略。请检查命名空间或FilterChainProxy bean配置中的排序

有人可以给我一个关于如何在每次访问index.jsp或admin.jsp时强制Spring提示输入凭据的指针,而不是假设应该使用现有的凭据吗?

2 个答案:

答案 0 :(得分:1)

每次访问index.jspadmin.jsp“时,您可能不需要Spring Security ”来提示输入凭据。 它不是Spring Security的常用用例,即使你设法做到这一点,它也会使事情变得更加复杂。

相反,您可以在用户访问应用程序的任何网页时对用户进行身份验证(即,您只需提示一次连接和密码)。当用户尝试访问admin.jsp时,您可以 使用您已经拥有的用户凭据来允许或拒绝访问此页面。

您需要在原始代码中将access="permitAll"替换为access="hasRole('user')"。那么你的<http> 标签应如下所示:

<http use-expressions="true">
    <intercept-url pattern="/admin.jsp" access="hasRole('administrator')" />
    <intercept-url pattern="/**" access="hasRole('user')" />
    <form-login login-page="/login.jsp" default-target-url="/admin.jsp" />
    <logout />
</http>

另外,请在<authentication-manager>代码中保留您自己的更改,但将authorities="administrator"替换为authorities="user,administrator"

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="${admin.username}" password="${admin.password}" authorities="user,administrator" />
            <user name="${user.username}" password="${user.password}" authorities="user" />
        </user-service>
    </authentication-provider>
</authentication-manager>

Spring Security按照<intercept-url>规则的顺序进行匹配。首先,它将检查所请求的页面是否与/admin.jsp模式匹配。如果是,则hasRole('administrator')将用作此页面的访问规则。所有其他页面将匹配/**模式。由于所有经过身份验证的用户(包括administrator)都属于user角色,因此所有其他页面都可供任何经过身份验证的用户使用。

您不能在<form-login>内使用多个<logout><http>标记。我还怀疑你可以在Spring配置中定义多个<http>部分。

有关配置Spring Security的详细信息,请参阅Spring Security Reference

<强>更新

另外,将default-target-url="/admin.jsp"替换为default-target-url="/index.jsp",因为您不希望将普通(非管理员)用户重定向到admin.jsp

答案 1 :(得分:0)

尝试使用'access-denied-handler',如下所示:

<http ...>
    ...
    <access-denied-handler error-page="the page you want to redirect to"/>
</http>