是否有相当于 Thymeleafs sec:authorize 标签的小胡子?
Is there a Mustache equivalent to Thymeleafs sec:authorize tag?
我正在努力移植带有 ThymeLeaf 模板的应用程序以使用 Mustache 模板,但我没有找到移植 ThymeLeaf 的 sec:authorize
标签的好方法。有没有办法像 Thymeleaf Spring 安全附加功能那样获取 Mustache 中的 SecurityContext
信息?
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
我以为我可以使用 @ControllerAdvice
像这样注入模型属性,但是 SecurityContextHolder.getContents().getAuthentication()
为空。但是,我能够很好地检查 HttpServletRequest
对象上的角色。这似乎是一个时间问题,因为在我的主要 @Controller
中,我能够访问 Authentication
对象。我可以提取主体名称和 isAuthenticated()
returns 正确的值。这是我尝试使用 @ControllerAdvice
:
package com.example;
import java.util.Map.Entry;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import org.example.security.entity.UserRole;
import org.example.security.entity.UserRole.Role;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class TemplateAdvice {
private static String ANONYMOUS_USER = "anonymousUser";
private Authentication authentication;
private Object principal;
private String username;
private boolean isAuthenticated;
private boolean isAnonymous;
private HttpServletRequest request;
public TemplateAdvice() {
this.authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (this.authentication != null) {
this.principal = this.authentication.getPrincipal();
this.username = this.authentication.getName();
}
this.isAnonymous = this.principal == null
|| this.username.equals(ANONYMOUS_USER);
}
@ModelAttribute
public void addDefaultAttributes(HttpServletRequest request,
Model model) {
this.request = request;
model.addAttribute("isAuthenticated", this.authentication.isAuthenticated());
model.addAttribute("isAnonymous", this.isAnonymous);
model.addAttribute("username", this.username);
model.addAttribute("isAuthenticated", hasAnyRole()); // hack
model.addAttribute("isAdminOrSuper",
hasRole(UserRole.Role.ADMIN)
|| hasRole(UserRole.Role.SUPER)); // this works
}
private boolean hasRole(Role role) {
return this.request.isUserInRole(role.name());
}
private boolean hasAnyRole() {
return Stream.of(UserRole.Role.values())
.anyMatch(role -> hasRole(role));
}
}
我正在使用
拉出 contextPath
和 _csrf.token
spring.mustache.expose-request-attributes=true
spring.mustache.request-context-attribute=req
并希望可以类似地公开一些安全上下文。
我在 Google 上找不到很多示例。有没有一种好方法来检查用户是否经过身份验证以及他们在 Mustache 模板中具有什么角色?
我确定问题之一是安全上下文未在 TemplateAdvice
构造函数中解析。将其移至 addDefaultAttributes
后,一切都按预期运行。这是我现在想到的:
package com.example.authentication.server.controller;
import javax.servlet.http.HttpServletRequest;
import com.example.authentication.server.security.SecurityHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class TemplateAdvice {
private SecurityHelper securityHelper;
@ModelAttribute
public void addDefaultAttributes(HttpServletRequest request, Model model) {
securityHelper = new SecurityHelper(SecurityContextHolder.getContext());
model.addAttribute("isLoggedIn", securityHelper.isAuthenticated()
&& !securityHelper.isAnonymous());
model.addAttribute("username", securityHelper.username());
model.addAttribute("isAdminOrSuper", securityHelper.isAdminOrSuper());
}
}
和对应的SecurityHelper
class:
package com.example.authentication.server.security;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
public class SecurityHelper {
public static enum Role {
ROLE_USER, ROLE_ADMIN;
}
private Collection<? extends GrantedAuthority> authorities =
Collections.emptyList();
private Authentication authentication;
public SecurityHelper(SecurityContext context) {
authentication = context.getAuthentication();
if (authentication != null) {
authorities = authentication.getAuthorities();
}
}
public boolean isAuthenticated() {
return authentication == null ? false : authentication.isAuthenticated();
}
public boolean isAnonymous() {
return authentication == null ? true :
authentication instanceof AnonymousAuthenticationToken;
}
public String username() {
return authentication == null ? "" : authentication.getName();
}
public boolean isAdminOrSuper() {
return hasAnyRole(Arrays.asList(Role.ROLE_ADMIN, Role.ROLE_SUPER));
}
/**
* Checks if user contains the given role.
*
* @param role
* A user role.
* @return True if the user contains the role.
*/
public boolean hasRole(Role role) {
return authorities == null ? false
: authorities.stream().anyMatch(authority ->
authority.getAuthority().equals(role.name()));
}
/**
* Checks if a user contains at least one of the roles.
*
* @param roles
* A list of user roles.
* @return True if the user contains one of the roles.
*/
public boolean hasAnyRole(List<Role> roles) {
return roles.stream().anyMatch(role -> hasRole(role));
}
}
我刚刚为 mustache 创建了一个启动器,以使用 spring 安全的 'Expression-Based Access Control' 功能,请检查此处的代码:
https://github.com/iceant/mustache-security-spring-boot-starter
示例如下:
{{#sec:hasRole('ADMIN')}}<li>ADMIN CONTENT</li>{{/sec:hasRole('ADMIN')}}
{{#sec:hasRole('ADMIN') and hasRole('USER')}}<li>ADMIN & USER CONTENT</li>{{/sec:hasRole('ADMIN') and hasRole('USER')}}
{{#sec:hasAnyRole('ADMIN', 'USER')}}<li>ADMIN OR USER CONTENT</li>{{/sec:hasAnyRole('ADMIN', 'USER')}}
{{#sec:hasRole('USER')}}<li>USER CONTENT</li>{{/sec:hasRole('USER')}}
{{#sec:isAnonymous()}}<li>isAnonymous</li>{{/sec:isAnonymous()}}{{^sec:isAnonymous()}}<li>isAnonymous=false</li>{{/sec:isAnonymous()}}
{{#sec:isRememberMe()}}<li>isRememberMe</li>{{/sec:isRememberMe()}}{{^sec:isRememberMe()}}<li>isRememberMe=false</li>{{/sec:isRememberMe()}}
{{#sec:isAuthenticated()}}<li>isAuthenticated</li>{{/sec:isAuthenticated()}}
{{^sec:isAuthenticated()}}<li>isAuthenticated=false</li>{{/sec:isAuthenticated()}}
{{#sec:isFullyAuthenticated()}}<li>isFullyAuthenticated</li>{{/sec:isFullyAuthenticated()}}
{{^sec:isFullyAuthenticated()}}<li>isFullyAuthenticated=false</li>{{/sec:isFullyAuthenticated()}}
{{#sec:principal}}<li>principal={{username}}{{/sec:principal}}
{{#sec:authentication}}<li>authentication={{.}}{{/sec:authentication}}
{{#sec:permitAll}}<li>permitAll</li>{{/sec:permitAll}}
{{#sec:denyAll}}<li>denyAll</li>{{/sec:denyAll}}
{{^sec:denyAll}}<li>denyAll=false</li>{{/sec:denyAll}}
{{^sec:hasIpAddress('192.168.2.1')}}<li>hasIpAddress('192.168.2.1')=false</li>{{/sec:hasIpAddress('192.168.2.1')}}
{{#sec:isMember(3)}}<li>isMember(3){{/sec:isMember(3)}}
{{#sec:@webSecurity.check(authentication,request)}}<li>@webSecurity.check(authentication,request){{/sec:@webSecurity.check(authentication,request)}}
我正在努力移植带有 ThymeLeaf 模板的应用程序以使用 Mustache 模板,但我没有找到移植 ThymeLeaf 的 sec:authorize
标签的好方法。有没有办法像 Thymeleaf Spring 安全附加功能那样获取 Mustache 中的 SecurityContext
信息?
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
我以为我可以使用 @ControllerAdvice
像这样注入模型属性,但是 SecurityContextHolder.getContents().getAuthentication()
为空。但是,我能够很好地检查 HttpServletRequest
对象上的角色。这似乎是一个时间问题,因为在我的主要 @Controller
中,我能够访问 Authentication
对象。我可以提取主体名称和 isAuthenticated()
returns 正确的值。这是我尝试使用 @ControllerAdvice
:
package com.example;
import java.util.Map.Entry;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import org.example.security.entity.UserRole;
import org.example.security.entity.UserRole.Role;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class TemplateAdvice {
private static String ANONYMOUS_USER = "anonymousUser";
private Authentication authentication;
private Object principal;
private String username;
private boolean isAuthenticated;
private boolean isAnonymous;
private HttpServletRequest request;
public TemplateAdvice() {
this.authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (this.authentication != null) {
this.principal = this.authentication.getPrincipal();
this.username = this.authentication.getName();
}
this.isAnonymous = this.principal == null
|| this.username.equals(ANONYMOUS_USER);
}
@ModelAttribute
public void addDefaultAttributes(HttpServletRequest request,
Model model) {
this.request = request;
model.addAttribute("isAuthenticated", this.authentication.isAuthenticated());
model.addAttribute("isAnonymous", this.isAnonymous);
model.addAttribute("username", this.username);
model.addAttribute("isAuthenticated", hasAnyRole()); // hack
model.addAttribute("isAdminOrSuper",
hasRole(UserRole.Role.ADMIN)
|| hasRole(UserRole.Role.SUPER)); // this works
}
private boolean hasRole(Role role) {
return this.request.isUserInRole(role.name());
}
private boolean hasAnyRole() {
return Stream.of(UserRole.Role.values())
.anyMatch(role -> hasRole(role));
}
}
我正在使用
拉出contextPath
和 _csrf.token
spring.mustache.expose-request-attributes=true
spring.mustache.request-context-attribute=req
并希望可以类似地公开一些安全上下文。
我在 Google 上找不到很多示例。有没有一种好方法来检查用户是否经过身份验证以及他们在 Mustache 模板中具有什么角色?
我确定问题之一是安全上下文未在 TemplateAdvice
构造函数中解析。将其移至 addDefaultAttributes
后,一切都按预期运行。这是我现在想到的:
package com.example.authentication.server.controller;
import javax.servlet.http.HttpServletRequest;
import com.example.authentication.server.security.SecurityHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class TemplateAdvice {
private SecurityHelper securityHelper;
@ModelAttribute
public void addDefaultAttributes(HttpServletRequest request, Model model) {
securityHelper = new SecurityHelper(SecurityContextHolder.getContext());
model.addAttribute("isLoggedIn", securityHelper.isAuthenticated()
&& !securityHelper.isAnonymous());
model.addAttribute("username", securityHelper.username());
model.addAttribute("isAdminOrSuper", securityHelper.isAdminOrSuper());
}
}
和对应的SecurityHelper
class:
package com.example.authentication.server.security;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
public class SecurityHelper {
public static enum Role {
ROLE_USER, ROLE_ADMIN;
}
private Collection<? extends GrantedAuthority> authorities =
Collections.emptyList();
private Authentication authentication;
public SecurityHelper(SecurityContext context) {
authentication = context.getAuthentication();
if (authentication != null) {
authorities = authentication.getAuthorities();
}
}
public boolean isAuthenticated() {
return authentication == null ? false : authentication.isAuthenticated();
}
public boolean isAnonymous() {
return authentication == null ? true :
authentication instanceof AnonymousAuthenticationToken;
}
public String username() {
return authentication == null ? "" : authentication.getName();
}
public boolean isAdminOrSuper() {
return hasAnyRole(Arrays.asList(Role.ROLE_ADMIN, Role.ROLE_SUPER));
}
/**
* Checks if user contains the given role.
*
* @param role
* A user role.
* @return True if the user contains the role.
*/
public boolean hasRole(Role role) {
return authorities == null ? false
: authorities.stream().anyMatch(authority ->
authority.getAuthority().equals(role.name()));
}
/**
* Checks if a user contains at least one of the roles.
*
* @param roles
* A list of user roles.
* @return True if the user contains one of the roles.
*/
public boolean hasAnyRole(List<Role> roles) {
return roles.stream().anyMatch(role -> hasRole(role));
}
}
我刚刚为 mustache 创建了一个启动器,以使用 spring 安全的 'Expression-Based Access Control' 功能,请检查此处的代码: https://github.com/iceant/mustache-security-spring-boot-starter
示例如下:
{{#sec:hasRole('ADMIN')}}<li>ADMIN CONTENT</li>{{/sec:hasRole('ADMIN')}}
{{#sec:hasRole('ADMIN') and hasRole('USER')}}<li>ADMIN & USER CONTENT</li>{{/sec:hasRole('ADMIN') and hasRole('USER')}}
{{#sec:hasAnyRole('ADMIN', 'USER')}}<li>ADMIN OR USER CONTENT</li>{{/sec:hasAnyRole('ADMIN', 'USER')}}
{{#sec:hasRole('USER')}}<li>USER CONTENT</li>{{/sec:hasRole('USER')}}
{{#sec:isAnonymous()}}<li>isAnonymous</li>{{/sec:isAnonymous()}}{{^sec:isAnonymous()}}<li>isAnonymous=false</li>{{/sec:isAnonymous()}}
{{#sec:isRememberMe()}}<li>isRememberMe</li>{{/sec:isRememberMe()}}{{^sec:isRememberMe()}}<li>isRememberMe=false</li>{{/sec:isRememberMe()}}
{{#sec:isAuthenticated()}}<li>isAuthenticated</li>{{/sec:isAuthenticated()}}
{{^sec:isAuthenticated()}}<li>isAuthenticated=false</li>{{/sec:isAuthenticated()}}
{{#sec:isFullyAuthenticated()}}<li>isFullyAuthenticated</li>{{/sec:isFullyAuthenticated()}}
{{^sec:isFullyAuthenticated()}}<li>isFullyAuthenticated=false</li>{{/sec:isFullyAuthenticated()}}
{{#sec:principal}}<li>principal={{username}}{{/sec:principal}}
{{#sec:authentication}}<li>authentication={{.}}{{/sec:authentication}}
{{#sec:permitAll}}<li>permitAll</li>{{/sec:permitAll}}
{{#sec:denyAll}}<li>denyAll</li>{{/sec:denyAll}}
{{^sec:denyAll}}<li>denyAll=false</li>{{/sec:denyAll}}
{{^sec:hasIpAddress('192.168.2.1')}}<li>hasIpAddress('192.168.2.1')=false</li>{{/sec:hasIpAddress('192.168.2.1')}}
{{#sec:isMember(3)}}<li>isMember(3){{/sec:isMember(3)}}
{{#sec:@webSecurity.check(authentication,request)}}<li>@webSecurity.check(authentication,request){{/sec:@webSecurity.check(authentication,request)}}