微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从Spring Security获取AuditorAware以将CreatedBy存储为UUID?

如何解决如何从Spring Security获取AuditorAware以将CreatedBy存储为UUID?

我正在尝试从登录用户获取UUID,并将其存储为“ CreatedBy”和“ LastUpdatedBy”,而不仅仅是字符串。但是,我遇到强制转换错误

java.lang.String不能转换为com.example.lims.container.Container类

下面的所有代码...谢谢!

大编辑:

我更改了ApplicationUser以实现SpringSecurity的UserDetails,并向我的BaseEntity添加了合法的映射关系。现在我得到一个新的例外。我很确定这与我从SecurityAuditAware返回的内容有关。我不知道如何获取它以返回正确的ApplicationUser实例。

java.lang.classCastException:无法将类java.lang.String强制转换为com.example.lims.user.ApplicationUser类(java.lang.String在加载程序'bootstrap'的模块java.base中; me.tmpjr .lims.user.ApplicationUser在加载程序org.springframework.boot.devtools.restart.classloader.RestartClassLoader @ 3d3e8a83的未命名模块中) 在com.example.lims.security.SecurityAuditorAware.getCurrentAuditor(SecurityAuditorAware.java:20)〜[classes /:na]

模式:

CREATE TABLE IF NOT EXISTS "containers" (
    id uuid NOT NULL,container_name VARCHAR(100) NOT NULL,created_by UUID NOT NULL,created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,updated_by UUID,updated_at TIMESTAMP WITHOUT TIME ZONE,PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS "users" (
    id uuid NOT NULL,username VARCHAR(100) NOT NULL,password VARCHAR(100) NOT NULL,created_by UUID,PRIMARY KEY (id)
);

BaseEntity AuditorAware:

@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected UUID id;

    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at")
    protected Date createdAt;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated_at")
    protected Date updatedAt;

    @CreatedBy
    @JoinColumn(name = "created_by",nullable = true,insertable = true,updatable = false)
    @ManyToOne
    protected ApplicationUser createdBy;

    @LastModifiedBy
    @JoinColumn(name = "updated_by",insertable = false,updatable = false)
    @ManyToOne
    protected ApplicationUser updatedBy;
}

ApplicationUser:

@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Valid
@Table(name = "users")
@NoArgsConstructor
public class ApplicationUser extends BaseEntity implements UserDetails 
{
    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String password;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

返回ApplicationUser的Security AuditorAware实现:

@Component
public class SecurityAuditorAware implements AuditorAware<ApplicationUser> {
    public Optional<ApplicationUser> getCurrentAuditor() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth == null || !auth.isAuthenticated()) {
            return Optional.empty();
        }
        // THIS is where I think it's going wrong.. what to return here? How to return ApplicationUser?
        return Optional.ofNullable((ApplicationUser) auth.getPrincipal());
    }
}

UserDetailsS​​erviceImpl:

@requiredArgsConstructor
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private final ApplicationUserRepository userRepository;

    @Override
    public ApplicationUser loadUserByUsername(String username) throws UsernameNotFoundException {
        ApplicationUser applicationUser = userRepository.findByUsername(username);
        if (applicationUser == null) {
            throw new UsernameNotFoundException(username);
        }

        return applicationUser;
    }
}

Bean配置:

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class PersistenceConfig {
    @Bean
    public AuditorAware<ApplicationUser> auditorAware() {
        return new SecurityAuditorAware();
    }
}

完全例外:

java.lang.classCastException: class java.lang.String cannot be cast to class com.example.lims.user.ApplicationUser (java.lang.String is in module java.base of loader 'bootstrap'; com.example.lims.user.ApplicationUser is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @3d3e8a83)
    at com.example.lims.security.SecurityAuditorAware.getCurrentAuditor(SecurityAuditorAware.java:21) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]

有效的解决方法

我相信我已经找到了问题。由于我使用的是UsernamePasswordAuthenticationToken,因此getPrinciple不会返回UserDetails对象。我根本无法将其转换为我的自定义Entity类。但是,如果我在SecurityAuditorAware中手动使用存储库搜索并将其直接返回,则可以正常工作!

@Component
@requiredArgsConstructor
public class SecurityAuditorAware implements AuditorAware<ApplicationUser> {
    private final ApplicationUserRepository userRepository;

    public Optional<ApplicationUser> getCurrentAuditor() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth == null || !auth.isAuthenticated()) {
            return Optional.empty();
        }

        return Optional.ofNullable((ApplicationUser) userRepository.findByUsername((auth.getName())));
    }
}

解决方法

change your id data type to Long

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;

然后您的安全审核员应该看起来像这样

public class SpringSecurityAuditorAware implements AuditorAware<Long> {

    

    @Override
    @Transactional(readOnly = false,propagation = Propagation.SUPPORTS)
    public Long getCurrentAuditor() {
        Authentication auth = 
        SecurityContextHolder.getContext().getAuthentication();
        
        return auth.getPrincipal().getId();
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。