Spring security jsp授权标签不起作用

Posted

技术标签:

【中文标题】Spring security jsp授权标签不起作用【英文标题】:Spring security jsp authorize tag not working 【发布时间】:2016-11-13 04:25:26 【问题描述】:

我有以下弹簧安全配置:

<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  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);

谢谢,提前!

【问题讨论】:

请在使用安全标签的地方显示完整的jsp代码。 @shazin 我粘贴了完整的jsp代码。 【参考方案1】:

经过几个小时的搜索和阅读 Spring Security 4 文档,我终于明白了问题的原因。

这里有一些来自 spring 文档的信息:

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') 表达式。

【讨论】:

【参考方案2】:

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

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

否则,您必须直接在安全标签中直接使用角色名称,

<sec:authorize access="ADMIN">
    <a href="/blog/createPost">Create post</a>
</sec:authorize>

【讨论】:

这里有一个简单的教程:mkyong.com/spring-security/… 文档告诉,默认use-expression="true"。无论如何,我尝试添加它,但没有帮助。尝试像access="ADMIN"一样直接检查,出现jsp异常。

以上是关于Spring security jsp授权标签不起作用的主要内容,如果未能解决你的问题,请参考以下文章

spring security3 动态从数据库中读取权限信息<sec:authorize>标签 url属性不起作用

Spring Security sec:授权抛出异常

使用 Spring Security 为非授权用户隐藏数据表中的按钮

添加“spring-security-taglibs”后jsp中仍然报错:找不到spring security标签的标签库描述符

Spring Security--Jsp标签

使用 Spring Security 的 Thymeleaf 授权不起作用[重复]