Spring安全jsp授权标签无效

时间:2016-07-11 09:17:45

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

我有以下弹簧安全配置:

<security:http auto-config="true">  
    <security:intercept-url pattern="/**" access="permitAll" />
    <security:form-login 
        login-processing-url="/j_spring_security_check"
        login-page="/login" 
        default-target-url="/" 
        authentication-failure-url="/login?error"
        username-parameter="login"
        password-parameter="password" />  
    <security:logout logout-url="/j_spring_security_logout" logout-success-url="/login" />
    <security:csrf disabled="true"/>
</security:http>

我想让每个人(经过身份验证的用户和未经过身份验证的用户)都可以访问特定页面(比如索引页面(“/”)),但同时,能够管理哪些部分应该在jsp取决于用户是否经过身份验证及其角色。

我的jsp部分看起来像这样:

<%@ page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:main>
    <jsp:attribute name="title">
        Posts
    </jsp:attribute>
    <jsp:body>
        <sec:authorize access="hasRole('ADMIN')">
            <a href="/blog/createPost">Create post</a>
        </sec:authorize>

        <br>

        <c:forEach var="post" items="${posts}">
            <hr width="300" align="left">
            <div>
                <h4><a href="/blog/viewPost/${post.id}">${post.title}</a></h4>
                <div>${post.content}</div>
            </div>
        </c:forEach>
    </jsp:body>
</t:main>

所有身份验证机制都可以。 问题在于,即使我使用“ADMIN”角色登录,也不会显示该链接。

我尝试调试我的UserDetailsS​​ervice实现,并验证“ADMIN”角色已成功获取并填充到userdetails中:

@Override
public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
    User user = userDao.findOneByLogin(login);

    if (user == null) {
        throw new UsernameNotFoundException(login + " not found");
    }

    List<GrantedAuthority> authList = new ArrayList<>();
    List<Role> roles = user.getRoles();

    for (Role role : roles) {
        authList.add(new SimpleGrantedAuthority(role.getName()));
    }

    return new org.springframework.security.core.userdetails.User(
            user.getLogin(), user.getPassword(), authList);
}

先谢谢!

2 个答案:

答案 0 :(得分:1)

您的问题似乎在配置中。要使用hasRolehasAnyRole表达式,您需要在use-expressions="true"代码中设置security:http

<security:http auto-config="true" use-expressions="true">  

否则,您必须直接在安全标记

中直接使用角色名称
<sec:authorize access="ADMIN">
    <a href="/blog/createPost">Create post</a>
</sec:authorize>

答案 1 :(得分:1)

经过几个小时的搜索和阅读Spring Security 4文档,最后,我意识到了问题的原因。

以下是spring docs的一些信息:

  

<强> hasRole([role])

     

如果当前主体具有指定的角色,则返回true。默认情况下,如果提供的角色不以“ROLE_”开头,则会添加该角色。这可以通过修改DefaultWebSecurityExpressionHandler上的defaultRolePrefix来自定义。

     

<强> hasAuthority([authority])

     

如果当前主体具有指定的权限,则返回true。

所以,根据上面的陈述,我们可以得出结论,默认情况下,Spring Security 4期望所有“角色”都以“ROLE_”前缀开头,而所有其他角色则以简单的权限/权限进行威胁。

在我的情况下,我在数据库中保存了“ADMIN”角色,每当我尝试检查像hasRole('ADMIN')这样的角色时Spring就将其转换为hasRole('ROLE_ADMIN'),从而将此表达式评估为false。

这里有两种类型的修复,要么我在数据库中将'ADMIN'角色重命名为'ROLE_ADMIN'(如Spring所期望的那样),要么使用hasAuthority('ADMIN')表达式。