Spring 安全 hasRole() 不工作
Spring Security hasRole() not working
我在使用 Spring Security && Thymeleaf 时遇到问题,特别是在尝试使用 hasRole 表达式时。 'admin' 用户有一个角色 'ADMIN' 但 hasRole('ADMIN')
无论如何都解析为 false 我试过了
我的html:
1.<div sec:authentication="name"></div> <!-- works fine -->
2.<div sec:authentication="principal.authorities"></div> <!-- works fine -->
3.<div sec:authorize="isAuthenticated()" >true</div> <!-- works fine -->
4.<span th:text="${#authorization.expression('isAuthenticated()')}"></span> <!-- works fine -->
5.<div th:text="${#vars.role_admin}"></div> <!--Works fine -->
6.<div sec:authorize="${hasRole('ADMIN')}" > IS ADMIN </div> <!-- Doesnt work -->
7.<div sec:authorize="${hasRole(#vars.role_admin)}" > IS ADMIN </div> <!-- Doesnt work -->
8.<div th:text="${#authorization.expression('hasRole(''ADMIN'')')} "></div> <!-- Doesnt work -->
9.<div th:text="${#authorization.expression('hasRole(#vars.role_admin)')}"></div> <!-- Doesnt work -->
结果:
1.admin
2.[ADMIN]
3.true
4.true
5.ADMIN
6."prints nothing because hasRole('ADMIN') resolves to false"
7."prints nothing because hasRole(#vars.role_admin) resolves to false"
8.false
9.false
我在我的 security.xml 文件中启用了 use-expressions
<security:http auto-config="true" use-expressions="true">
并且还在我的配置中包含 SpringSecurityDialect
<bean id="templateEngine"
class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect" />
</set>
</property>
</bean>
我的 pom.xml 文件中的所有必要依赖项
<!--Spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<!--Thymeleaf Spring Security-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
Role.java
@Entity
@Table(name = "roles")
public class Role implements Serializable {
@Id
@Enumerated(EnumType.STRING)
private RoleType name;
//... getters, setters
}
角色类型
public enum RoleType {
ADMIN
}
并且User
有一组Role
为什么 hasRole()
不起作用?
感谢您的帮助,谢谢
解决方法
th:if="${#strings.contains(#authentication.principal.authorities,'ADMIN')}"
参考官方文档。 http://www.thymeleaf.org/doc/articles/springsecurity.html
<div sec:authorize="hasRole('ROLE_ADMIN')">
This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
This content is only shown to users.
</div>
你能不能在没有 ${
... }
.
的情况下简单地尝试一下
<div sec:authorize="hasRole('ADMIN')">IS ADMIN</div>
我相信你没有在角色前面加上 ROLE_
。如果是这样,请确保像下面一样添加前缀
<div sec:authorize="hasRole('ROLE_ADMIN')">IS ADMIN</div>
我不得不在需要验证用户角色的地方做类似的事情。我在下面做了
<div th:if="${ #authorization.expression('isAuthenticated()') and #strings.contains(#authentication.principal.authorities,'ADMIN')}">
<a th:href="@{/somelink}">ADMIN LINK</a>
</div>
希望对大家有所帮助。
我最近遇到了同样的问题。
您需要做的是:
在您的 html 中添加以下语句:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
(您可以根据使用的内容在 springsecurity4 或 springsecurity3 之间切换)。
确保您已将此资源添加到您的图书馆。我正在使用 gradle,但您可以对 Maven 执行相同的操作。
compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE'
在您的 SpringWebConfiguration class 或 xml 中确保您正在为 thymeleaf SpringSecurity 添加方言:
我正在使用 java class 进行配置。
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new SpringSecurityDialect());
return templateEngine;
}
但你也可以定义为 alexsource 说:
Spring security and Thymeleaf doesn't work
希望这对你有用!
您好!
尝试在 HTML-tag 中使用 hasAuthority
而不是 hasRole
。
sec:authorize="hasAuthority('ADMIN')"
我遇到了同样的问题,这是因为 spring-security
4.0
。由于某些原因 thymeleaf-extras-springsecurity4
与 spring-security
4.0 和 thymeleaf
2.x
不兼容。
所以我将 spring-security
版本降级为 3.2.9.RELEASE
并且它开始工作了。
如果您仍然想使用 spring-security 4.0
,那么您可以尝试将 thymeleaf-extras-springsecurity4
提升到 3.0.0.RELEASE
并将 thymeleaf
verison 提升到 3.0
或者如果您正在使用 spring 启动应用程序,那么情况会变得更加棘手,那么剩下的唯一选择就是降级 spring-security
或升级 spring 启动版本为 1.4.x(仍处于测试阶段)
在您的具体情况下,进行以下 pom 更改应该会使 hasRole 正常工作
<!--Spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<!--Thymeleaf Spring Security-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
我在从 Spring 安全 3.x 升级到 4.x 时遇到了同样的问题。将 hasRole()
更改为 hasAuthority()
对我有用。
http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-common-built-in
你错过了一个概念:
- 如果您使用
hasRole('ADMIN')
,您的 ADMIN Enum
必须是 ROLE_ADMIN
而不是 ADMIN
。
- 如果您使用
hasAuthority('ADMIN')
,您的 ADMIN Enum
必须是 ADMIN
。
在spring安全中,hasRole()
与hasAuthority()
相同,但hasRole()
功能映射与Authority
没有ROLE_
前缀。
您可以在此 post 中找到已接受的答案:Difference between Role and GrantedAuthority in Spring Security
经过数周的反复试验,这对我有用:
升级到最新版本
Spring 引导程序
Thymeleaf Extras Spring 安全 5
Spring Boot
的 Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
真的不知道哪个版本的依赖项可以与其他版本一起使用,但目前(2020 年 5 月 19 日)它对我有用。
希望对大家有所帮助
在Spring引导2中,
您可以使用 hasRole() 或 hasAuthority()。不同之处在于,您必须为 hasAusthority() 方法使用 ROLE_。所以对于 ROLE_ADMIN,
@PreAuthorize("hasRole('ADMIN')") == @PreAuthorize("hasAuthority('ROLE_ADMIN')")
我遇到了类似的问题,我解决了它。
我使用以下实体
用户实体
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class User implements UserDetails, CredentialsContainer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,unique = true)
private String username;
@Column(nullable = false,unique = true)
private String email;
private String password;
@Builder.Default
private Boolean accountNonExpired = true;
@Builder.Default
private Boolean accountNonLocked = true;
@Builder.Default
private Boolean credentialsNonExpired = true;
@Builder.Default
private Boolean enabled = true;
@CreationTimestamp
@Column(updatable = false)
private Timestamp createdDate;
@UpdateTimestamp
private Timestamp lastModifiedDate;
@Singular
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles = new HashSet<>();
@Override
public void eraseCredentials() {
this.password = null;
}
@Override
@Transient
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<SimpleGrantedAuthority> authorities =
this.roles.stream().
map(Role::getAuthorities).
flatMap(Set::stream).
map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
collect(Collectors.toSet());
roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return enabled;
}
}
角色实体
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
@Singular
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "role_authority",
joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")
)
private Set<Authority> authorities = new HashSet<>();
}
权威实体
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Authority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
private String permission;
@Singular
@ManyToMany(mappedBy = "authorities")
private Set<Role> roles = new HashSet<>();
}
自举
var storeItemCreate = authorityRepository.save(Authority.builder().permission("store.item.create").build());
var storeItemRead = authorityRepository.save(Authority.builder().permission("store.item.read").build());
var storeItemUpdate = authorityRepository.save(Authority.builder().permission("store.item.update").build());
var storeItemDelete = authorityRepository.save(Authority.builder().permission("store.item.delete").build());
var admin = roleRepository.save(Role.builder().
authority(storeItemCreate).
authority(storeItemRead).
authority(storeItemUpdate).
authority(storeItemDelete).
name("ROLE_ADMIN").build());
var customer = roleRepository.save(Role.builder().
authority(storeItemRead).
name("ROLE_CUSTOMER").
build());
userRepository.save(User.builder().
role(admin).
username("admin").
password(passwordEncoder.encode("admin")).
email("admin@admin.com").
build()
);
userRepository.save(User.builder().
role(customer).
username("user").
password(passwordEncoder.encode("user")).
email("user@user.com").
build()
);
我工作 hasAuthority() 和 hasRole() 的原因是 getAuthorities 方法中用户实体的片段
Set<SimpleGrantedAuthority> authorities =
this.roles.stream().
map(Role::getAuthorities).
flatMap(Set::stream).
map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
collect(Collectors.toSet());
roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
return authorities;
当您对名称具有权限时 ROLE_NAMEOFROLE spring 将其视为角色
当前缀不存在时 spring 将其视为权限。
记得要有权限:“ROLE_ADMIN”
我不确定这是正确的方法!!!
@组件
public class LoginSuccessHandler 扩展了 SavedRequestAwareAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
String redirectURL = request.getContextPath();
if (userDetails.hasRole("ROLE_ADMIN")) {
redirectURL = "admin-dashboard";
} else if (userDetails.hasRole("ROLE_EMPLOYEE")) {
redirectURL = "dashboard";
} else if (userDetails.hasRole("ROLE_TRAINEE")) {
redirectURL = "dashboard";
}
response.sendRedirect(redirectURL);
}
}
在我的例子中,hasRole
不适用于特定控制器的端点,但它适用于其他控制器端点。
我发现这个控制器在@RestController
之后有@RequestMapping
。
@RestController
@RequestMapping("/test/v1")
public class TestController {
}
我更改了顺序,hasRole
正在工作:
@RequestMapping("/test/v1")
@RestController
public class TestController {
}
我在使用 Spring Security && Thymeleaf 时遇到问题,特别是在尝试使用 hasRole 表达式时。 'admin' 用户有一个角色 'ADMIN' 但 hasRole('ADMIN')
无论如何都解析为 false 我试过了
我的html:
1.<div sec:authentication="name"></div> <!-- works fine -->
2.<div sec:authentication="principal.authorities"></div> <!-- works fine -->
3.<div sec:authorize="isAuthenticated()" >true</div> <!-- works fine -->
4.<span th:text="${#authorization.expression('isAuthenticated()')}"></span> <!-- works fine -->
5.<div th:text="${#vars.role_admin}"></div> <!--Works fine -->
6.<div sec:authorize="${hasRole('ADMIN')}" > IS ADMIN </div> <!-- Doesnt work -->
7.<div sec:authorize="${hasRole(#vars.role_admin)}" > IS ADMIN </div> <!-- Doesnt work -->
8.<div th:text="${#authorization.expression('hasRole(''ADMIN'')')} "></div> <!-- Doesnt work -->
9.<div th:text="${#authorization.expression('hasRole(#vars.role_admin)')}"></div> <!-- Doesnt work -->
结果:
1.admin
2.[ADMIN]
3.true
4.true
5.ADMIN
6."prints nothing because hasRole('ADMIN') resolves to false"
7."prints nothing because hasRole(#vars.role_admin) resolves to false"
8.false
9.false
我在我的 security.xml 文件中启用了 use-expressions
<security:http auto-config="true" use-expressions="true">
并且还在我的配置中包含 SpringSecurityDialect
<bean id="templateEngine"
class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect" />
</set>
</property>
</bean>
我的 pom.xml 文件中的所有必要依赖项
<!--Spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<!--Thymeleaf Spring Security-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
Role.java
@Entity
@Table(name = "roles")
public class Role implements Serializable {
@Id
@Enumerated(EnumType.STRING)
private RoleType name;
//... getters, setters
}
角色类型
public enum RoleType {
ADMIN
}
并且User
有一组Role
为什么 hasRole()
不起作用?
感谢您的帮助,谢谢
解决方法
th:if="${#strings.contains(#authentication.principal.authorities,'ADMIN')}"
参考官方文档。 http://www.thymeleaf.org/doc/articles/springsecurity.html
<div sec:authorize="hasRole('ROLE_ADMIN')">
This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
This content is only shown to users.
</div>
你能不能在没有 ${
... }
.
<div sec:authorize="hasRole('ADMIN')">IS ADMIN</div>
我相信你没有在角色前面加上 ROLE_
。如果是这样,请确保像下面一样添加前缀
<div sec:authorize="hasRole('ROLE_ADMIN')">IS ADMIN</div>
我不得不在需要验证用户角色的地方做类似的事情。我在下面做了
<div th:if="${ #authorization.expression('isAuthenticated()') and #strings.contains(#authentication.principal.authorities,'ADMIN')}">
<a th:href="@{/somelink}">ADMIN LINK</a>
</div>
希望对大家有所帮助。
我最近遇到了同样的问题。 您需要做的是:
在您的 html 中添加以下语句:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
(您可以根据使用的内容在 springsecurity4 或 springsecurity3 之间切换)。
确保您已将此资源添加到您的图书馆。我正在使用 gradle,但您可以对 Maven 执行相同的操作。
compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE'
在您的 SpringWebConfiguration class 或 xml 中确保您正在为 thymeleaf SpringSecurity 添加方言: 我正在使用 java class 进行配置。
@Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver()); templateEngine.addDialect(new SpringSecurityDialect()); return templateEngine; }
但你也可以定义为 alexsource 说: Spring security and Thymeleaf doesn't work
希望这对你有用! 您好!
尝试在 HTML-tag 中使用 hasAuthority
而不是 hasRole
。
sec:authorize="hasAuthority('ADMIN')"
我遇到了同样的问题,这是因为 spring-security
4.0
。由于某些原因 thymeleaf-extras-springsecurity4
与 spring-security
4.0 和 thymeleaf
2.x
不兼容。
所以我将 spring-security
版本降级为 3.2.9.RELEASE
并且它开始工作了。
如果您仍然想使用 spring-security 4.0
,那么您可以尝试将 thymeleaf-extras-springsecurity4
提升到 3.0.0.RELEASE
并将 thymeleaf
verison 提升到 3.0
或者如果您正在使用 spring 启动应用程序,那么情况会变得更加棘手,那么剩下的唯一选择就是降级 spring-security
或升级 spring 启动版本为 1.4.x(仍处于测试阶段)
在您的具体情况下,进行以下 pom 更改应该会使 hasRole 正常工作
<!--Spring security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<!--Thymeleaf Spring Security-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
我在从 Spring 安全 3.x 升级到 4.x 时遇到了同样的问题。将 hasRole()
更改为 hasAuthority()
对我有用。
http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-common-built-in
你错过了一个概念:
- 如果您使用
hasRole('ADMIN')
,您的ADMIN Enum
必须是ROLE_ADMIN
而不是ADMIN
。 - 如果您使用
hasAuthority('ADMIN')
,您的ADMIN Enum
必须是ADMIN
。
在spring安全中,hasRole()
与hasAuthority()
相同,但hasRole()
功能映射与Authority
没有ROLE_
前缀。
您可以在此 post 中找到已接受的答案:Difference between Role and GrantedAuthority in Spring Security
经过数周的反复试验,这对我有用:
升级到最新版本Spring 引导程序 Thymeleaf Extras Spring 安全 5 Spring Boot
的 Thymeleaf<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
真的不知道哪个版本的依赖项可以与其他版本一起使用,但目前(2020 年 5 月 19 日)它对我有用。
希望对大家有所帮助
在Spring引导2中, 您可以使用 hasRole() 或 hasAuthority()。不同之处在于,您必须为 hasAusthority() 方法使用 ROLE_。所以对于 ROLE_ADMIN,
@PreAuthorize("hasRole('ADMIN')") == @PreAuthorize("hasAuthority('ROLE_ADMIN')")
我遇到了类似的问题,我解决了它。
我使用以下实体
用户实体
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class User implements UserDetails, CredentialsContainer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,unique = true)
private String username;
@Column(nullable = false,unique = true)
private String email;
private String password;
@Builder.Default
private Boolean accountNonExpired = true;
@Builder.Default
private Boolean accountNonLocked = true;
@Builder.Default
private Boolean credentialsNonExpired = true;
@Builder.Default
private Boolean enabled = true;
@CreationTimestamp
@Column(updatable = false)
private Timestamp createdDate;
@UpdateTimestamp
private Timestamp lastModifiedDate;
@Singular
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles = new HashSet<>();
@Override
public void eraseCredentials() {
this.password = null;
}
@Override
@Transient
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<SimpleGrantedAuthority> authorities =
this.roles.stream().
map(Role::getAuthorities).
flatMap(Set::stream).
map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
collect(Collectors.toSet());
roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return enabled;
}
}
角色实体
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
@Singular
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "role_authority",
joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")
)
private Set<Authority> authorities = new HashSet<>();
}
权威实体
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Authority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
private String permission;
@Singular
@ManyToMany(mappedBy = "authorities")
private Set<Role> roles = new HashSet<>();
}
自举
var storeItemCreate = authorityRepository.save(Authority.builder().permission("store.item.create").build());
var storeItemRead = authorityRepository.save(Authority.builder().permission("store.item.read").build());
var storeItemUpdate = authorityRepository.save(Authority.builder().permission("store.item.update").build());
var storeItemDelete = authorityRepository.save(Authority.builder().permission("store.item.delete").build());
var admin = roleRepository.save(Role.builder().
authority(storeItemCreate).
authority(storeItemRead).
authority(storeItemUpdate).
authority(storeItemDelete).
name("ROLE_ADMIN").build());
var customer = roleRepository.save(Role.builder().
authority(storeItemRead).
name("ROLE_CUSTOMER").
build());
userRepository.save(User.builder().
role(admin).
username("admin").
password(passwordEncoder.encode("admin")).
email("admin@admin.com").
build()
);
userRepository.save(User.builder().
role(customer).
username("user").
password(passwordEncoder.encode("user")).
email("user@user.com").
build()
);
我工作 hasAuthority() 和 hasRole() 的原因是 getAuthorities 方法中用户实体的片段
Set<SimpleGrantedAuthority> authorities =
this.roles.stream().
map(Role::getAuthorities).
flatMap(Set::stream).
map(authority -> new SimpleGrantedAuthority(authority.getPermission())).
collect(Collectors.toSet());
roles.stream().map(Role::getName).map(SimpleGrantedAuthority::new).forEach(authorities::add);//WE NEED IT FOR hasRole() functionality
return authorities;
当您对名称具有权限时 ROLE_NAMEOFROLE spring 将其视为角色 当前缀不存在时 spring 将其视为权限。
记得要有权限:“ROLE_ADMIN”
我不确定这是正确的方法!!!
@组件 public class LoginSuccessHandler 扩展了 SavedRequestAwareAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
String redirectURL = request.getContextPath();
if (userDetails.hasRole("ROLE_ADMIN")) {
redirectURL = "admin-dashboard";
} else if (userDetails.hasRole("ROLE_EMPLOYEE")) {
redirectURL = "dashboard";
} else if (userDetails.hasRole("ROLE_TRAINEE")) {
redirectURL = "dashboard";
}
response.sendRedirect(redirectURL);
}
}
在我的例子中,hasRole
不适用于特定控制器的端点,但它适用于其他控制器端点。
我发现这个控制器在@RestController
之后有@RequestMapping
。
@RestController
@RequestMapping("/test/v1")
public class TestController {
}
我更改了顺序,hasRole
正在工作:
@RequestMapping("/test/v1")
@RestController
public class TestController {
}