通过Spring安全和斯佩尔表达式限制POST和REST请求时出错



如果需要,这里是我的小项目的GitHub。

我不懂拼写表达式。当我尝试实现本教程中的代码时,会出现以下错误:

1。

@PreAuthorize("hasRole('ROLE_USER')")
public interface TodoRepo extends PagingAndSortingRepository<TodoEntity, Long> {
@Override
@PreAuthorize("#todo?.entity == null or #todo?.entity?.name == authentication?.name")
TodoEntity save(@Param("todo") TodoEntity employee);
@Override
@PreAuthorize("@todoRepo.findById(#id)?.entity?.name == authentication?.name")
void deleteById(@Param("id") Long id);
@Override
@PreAuthorize("#todo?.entity?.name == authentication?.name")
void delete(@Param("todo") TodoEntity employee);
}
错误:

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'name' cannot be found on object of type 'com.egor.todo.entity.UserEntity' - maybe not public or not valid?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.OpEQ.getValueInternal(OpEQ.java:42) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.OpEQ.getValueInternal(OpEQ.java:32) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:188) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.OpOr.getBooleanValue(OpOr.java:56) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:51) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.OpOr.getValueInternal(OpOr.java:37) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:309) ~[spring-expression-5.3.23.jar:5.3.23]
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30) ~[spring-security-core-5.7.4.jar:5.7.4]
... 17 common frames omitted
  • @PreAuthorize("hasRole('ROLE_USER')")
    public interface TodoRepo extends PagingAndSortingRepository<TodoEntity, Long> {
    @Override
    @PreAuthorize("#todo?.getEntity() == null or #todo?.getEntity()?.getName() == authentication?.name")
    TodoEntity save(@Param("todo") TodoEntity employee);
    
    @Override
    @PreAuthorize("@todoRepo.findById(#id)?.getEntity()?.getName() == authentication?.name")
    void deleteById(@Param("id") Long id);
    
    @Override
    @PreAuthorize("#todo?.getEntity()?.getName() == authentication?.name")
    void delete(@Param("todo") TodoEntity employee);
    }
    

    错误:

    Caused by: org.springframework.security.access.AccessDeniedException: Доступ запрещен
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:239) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:58) ~[spring-security-core-5.7.4.jar:5.7.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.23.jar:5.3.23]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.23.jar:5.3.23]
    at jdk.proxy2/jdk.proxy2.$Proxy107.save(Unknown Source) ~[na:na]
    at com.egor.todo.DatabaseLoader.run(DatabaseLoader.java:40) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771) ~[spring-boot-2.7.5.jar:2.7.5]
    ... 5 common frames omitted
    

    实体:

    TodoEntity.java

    package com.egor.todo.entity;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToOne;
    import java.util.Objects;
    @Entity
    public class TodoEntity {
    private @Id @GeneratedValue long id;
    private String name;
    private String description;
    private boolean done;
    private @ManyToOne UserEntity entity;
    public UserEntity getEntity() {
    return entity;
    }
    public void setEntity(UserEntity entity) {
    this.entity = entity;
    }
    public TodoEntity() {
    }
    public TodoEntity(String name, String description, boolean done, UserEntity entity) {
    this.name = name;
    this.description = description;
    this.done = done;
    this.entity = entity;
    }
    public long getId() {
    return id;
    }
    public void setId(long id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getDescription() {
    return description;
    }
    public void setDescription(String description) {
    this.description = description;
    }
    public boolean isDone() {
    return done;
    }
    public void setDone(boolean done) {
    this.done = done;
    }
    @Override
    public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    TodoEntity that = (TodoEntity) o;
    return id == that.id && done == that.done && Objects.equals(name, that.name) && Objects.equals(description, that.description);
    }
    @Override
    public int hashCode() {
    return Objects.hash(id, name, description, done);
    }
    @Override
    public String toString() {
    return "TodoEntity{" +
    "id=" + id +
    ", name='" + name + ''' +
    ", description='" + description + ''' +
    ", done=" + done +
    '}';
    }
    }
    

    UserEntity.java

    package com.egor.todo.entity;
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.util.Arrays;
    import java.util.Objects;
    @Entity
    public class UserEntity {
    public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
    private @Id @GeneratedValue Long id;
    private String name;
    private @JsonIgnore String password;
    private String[] roles;
    public void setPassword(String password) {
    this.password = PASSWORD_ENCODER.encode(password);
    }
    public UserEntity() {}
    public UserEntity(String name, String password, String... roles) {
    this.name = name;
    this.setPassword(password);
    this.roles = roles;
    }
    @Override
    public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    UserEntity entity = (UserEntity) o;
    return Objects.equals(id, entity.id) &&
    Objects.equals(name, entity.name) &&
    Objects.equals(password, entity.password) &&
    Arrays.equals(roles, entity.roles);
    }
    @Override
    public int hashCode() {
    int result = Objects.hash(id, name, password);
    result = 31 * result + Arrays.hashCode(roles);
    return result;
    }
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getPassword() {
    return password;
    }
    public String[] getRoles() {
    return roles;
    }
    public void setRoles(String[] roles) {
    this.roles = roles;
    }
    @Override
    public String toString() {
    return "UserEntity{" +
    "id=" + id +
    ", name='" + name + ''' +
    ", roles=" + Arrays.toString(roles) +
    '}';
    }
    }
    

    我在:

    将调用字段改为getter和返回。

    问题未解决。怎么啦?

    更新日志:

    1. 我添加了一个实体代码。

    结果是,我在调用"public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities)";构造函数。必须在"中输入相同的值。principal";字段,如"name";字段。

    最新更新