我一直在寻找已经接近我的问题,但似乎无法找到我正在寻找的确切答案。我猜想我想要做的解决方案非常简单。
我有一个带有默认页面的网站(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提示输入凭据的指针,而不是假设应该使用现有的凭据吗?
答案 0 :(得分:1)
每次访问index.jsp
或admin.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>