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



我一直在查找已经提出的与我密切相关的问题,但似乎找不到我正在寻找的确切答案。 我猜我想做的事情的解决方案相当简单。

我有一个带有默认页面(索引.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>   

我现在也需要密码保护索引.jsp 如果我复制元素的子元素(并且我创建了单独的登录.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>

然后,索引.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 配置中的顺序

任何人都可以给我一个指示,说明如何强制 Spring 在每次访问索引或 admin.jsp 时提示输入凭据.jsp而不是假设应该使用现有凭据?

您可能不需要 Spring 安全性"在每次访问index.jspadmin.jsp时提示输入凭据"。对于Spring Security来说,这不是一个通常的用例,即使你设法做到了,它也会让事情变得更加复杂。

相反,您可以在他/她访问应用程序的任何网页时对用户进行身份验证(即您只提示输入一次 ligin 和密码)。当用户尝试访问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 安全性按照规则的定义顺序匹配<intercept-url>规则。首先,它将检查请求的页面是否与/admin.jsp模式匹配。如果是这样,hasRole('administrator')将用作此页面的访问规则。所有其他页面将匹配/**模式。由于所有经过身份验证的用户(包括administrator)都属于user角色,因此所有其他页面都可供任何经过身份验证的用户使用。

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

有关配置 Spring 安全性的更多详细信息,请参阅 Spring 安全性参考。

更新

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

尝试像这样使用"访问拒绝处理程序":

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

最新更新