如何解决如何从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());
}
}
UserDetailsServiceImpl:
@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 举报,一经查实,本站将立刻删除。