在JSP EL表达式中获取Spring Security Principal

46

我正在使用Spring MVC和Spring Security 3.0.6.RELEASE版本。在我的JSP中,获取用户名最简单的方法是什么?或者仅仅知道用户是否已登录?我能想到两种方式:

1. 使用脚本片段

使用像这样的脚本片段来确定用户是否已登录:

<%=org.springframework.security.core.context.SecurityContextHolder.getContext()
    .getAuthentication().getPrincipal().equals("anonymousUser")
    ? "false":"true"%>

我不喜欢使用脚本片段,但我想在一些标签中使用它,这需要将其作为页面属性放回。

2. 使用SecurityContextHolder

我可以再次从我的@Controller中使用SecurityContextHolder,并将其放在模型上。但我需要在每个页面上都用到这个,所以我不想在每个控制器中都添加这个逻辑。

我猜应该有一种更简洁的方法来实现这个...

11个回答

61

5
完美!如果其他人看到这个问题,我需要在spring-security.xml中添加<bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />才能使它工作。 - Jeremiah Orr
6
太好了,好多了!如果其他人也遇到这个问题,我在我的pom.xml文件中添加了spring-security-taglibs依赖,这样就不会再忽略我的Spring安全标签了。 - user64141

20

我知道这个帖子中有其他答案,但没有一个回答了如何检查用户是否已验证身份。因此,我分享一下我的代码是什么样子的。

在你的项目中包含标签库:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

然后通过添加以下内容在当前作用域中创建一个用户对象:

<sec:authentication var="user" property="principal" />

接下来,您可以通过添加以下内容轻松显示用户名。请记住,“principal”对象通常是字符串类型,除非您已经以某种方式实现了Spring Security将其更改为项目中的另一个类:

然后您可以通过添加以下内容轻松显示用户名。请记住,“principal”对象通常是字符串类型,除非您已经以某种方式实现了 Spring Security 将其更改为项目中的另一个类:

<sec:authorize access="hasRole('ROLE_USER') and isAuthenticated()">
${user}
</sec:authorize>

我希望这能帮助到想要检查用户角色的人。

如果您正在使用Maven,则可以像Christian Vielma在此主题中提到的那样添加依赖标签。

谢谢!


11

您可以像这样使用: Spring Security 标签库 - 3.1.3.RELEASE

<sec:authentication var="principal" property="principal" />

然后:

${principal.username}

10

我在使用Maven,所以我必须将taglibs库添加到pom.xml中。

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>

然后在我的JSP中添加:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

而且:

<sec:authentication property="principal" />

principal.username 一直给我报错(可能是我创建 UsernamePasswordAuthenticationToken 对象的方式不对,但我不确定)。


5

我认为 <sec:authentication property="principal.username" /> 不总是有效,因为由 Authentication.getPrincipal() 返回的类型是 Object,即可能是 UserDetails (对于这种情况上述代码有效),也可能是 String 或其他任何类型。

如果想在 JSP 页面中显示用户名,我发现更可靠的方法是使用 ${pageContext.request.userPrincipal.name}

这将使用 java.security.Principal.getName() 方法,该方法返回一个字符串。


在使用匿名身份验证时,似乎无法正常工作。 - Neil McGuigan

5

无论用户是否已登录,以及使用匿名身份验证时,此功能均有效:

<sec:authorize access="isAuthenticated()">
    <sec:authentication property="principal.username" var="username" />
</sec:authorize>
<sec:authorize access="!isAuthenticated()">
    <sec:authentication property="principal" var="username" />
</sec:authorize>

Later...

Hello ${username}

5

我同意alephx的观点,甚至投了他的答案。

但如果你需要另一种方法,你可以使用Spring Roo使用的方法。

如果你有SecurityContextHolderAwareRequestFilter,它提供了标准的servlet API安全方法,使用一个访问SecurityContext的请求包装器。

这个过滤器在Spring Security命名空间的<http>标签中注册。你也可以将它注册到FilterChainProxy的安全过滤器链中(只需在你的applicationContext-security.xml中添加对已声明bean的引用)

然后,你可以像Roo一样访问安全servlet API(查找footer.jspx以查看如何编写条件注销链接)

  <c:if test="${pageContext['request'].userPrincipal != null}">
<c:out value=" | "/>
...


3

j标签是:

<%@taglib prefix="j" uri="http://java.sun.com/jsp/jstl/core" %>

安全标签是:

<%@taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

添加到pom.xml文件中:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>

添加到页面:

<sec:authentication var="principal" property="principal"/>
<j:choose>
    <j:when test="${principal eq 'anonymousUser'}">
          NOT AUTHENTICATED
    </j:when>
    <j:otherwise>
          AUTHENTICATED
    </j:otherwise>
</j:choose>

谢谢!正确答案适用于Spring Boot的新版本。 - Debadatta

1

我尝试过了,至少使用${request.userPrincipal}表达式,但它返回null。也许我做了什么破坏它的事情...不过还是谢谢! - Jeremiah Orr
@Jeremiah Orr,这很奇怪,我有几个应用程序都依赖于Spring Security和Servlet API之间的集成。也许您指定了自定义的Spring Security堆栈而不是使用默认的堆栈? - gpeche

1

要访问主属性,请首先为属性创建一个变量:

<sec:authentication property="principal.attributes" var="principalAttr"/>

然后,您可以使用此映射按属性键名称检索值:
${principalAttr.get("given_name")}

不要忘记在你的Maven依赖列表中添加Spring Security标签库:
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>5.3.4.RELEASE</version>
    </dependency>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接