我一直在查找已经提出的与我密切相关的问题,但似乎找不到我正在寻找的确切答案。 我猜我想做的事情的解决方案相当简单。
我有一个带有默认页面(索引.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.jsp
或admin.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>