我们在应用程序中使用Hibernate / JPA,Spring,Spring Data和Spring
Security。我有一个User
使用JPA映射的标准实体。此外,我有一个UserRepository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByUsername(String username);
}
它遵循Spring Data约定来命名查询方法。我有一个实体
@Entity
public class Foo extends AbstractAuditable<User, Long> {
private String name;
}
我想使用Spring Data审核支持。(如此处所述。)因此,我创建了一个AuditorService
如下:
@Service
public class AuditorService implements AuditorAware<User> {
private UserRepository userRepository;
@Override
public User getCurrentAuditor() {
String username = SecurityContextHolder.getContext().getAuthentication().getName();
List<User> users = userRepository.findByUsername(username);
if (users.size() > 0) {
return users.get(0);
} else {
throw new IllegalArgumentException();
}
}
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
当我创建一个方法时
@Transactional
public void createFoo() {
Foo bar = new Foo();
fooRepository.save(foo);
}
一切都正确接线的地方FooRepository
是Spring Data
CrudRepository
。然后,将StackOverflowError
引发a
,因为对的调用findByUsername
似乎触发了hibernate,以将数据刷新到数据库,从而触发了AuditingEntityListener
谁的调用AuditorService#getCurrentAuditor
,再次触发了刷新等。
如何避免这种递归?是否有“规范的方式”加载User
实体?还是有办法防止Hibernate / JPA刷新?
解决方案是不获取实现中的User
记录AuditorAware
。这会触发所描述的循环,因为选择查询会触发刷新(这种情况是因为Hibernate /
JPA希望在执行选择之前将数据写入数据库以提交事务),从而触发对的调用AuditorAware#getCurrentAuditor
。
解决方案是将User
记录存储在UserDetails
提供给Spring Security的文件中。因此,我创建了自己的实现:
public class UserAwareUserDetails implements UserDetails {
private final User user;
private final Collection<? extends GrantedAuthority> grantedAuthorities;
public UserAwareUserDetails(User user) {
this(user, new ArrayList<GrantedAuthority>());
}
public UserAwareUserDetails(User user, Collection<? extends GrantedAuthority> grantedAuthorities) {
this.user = user;
this.grantedAuthorities = grantedAuthorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return grantedAuthorities;
}
@Override
public String getPassword() {
return user.getSaltedPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public User getUser() {
return user;
}
}
此外,我更改UserDetailsService
了加载User
并创建UserAwareUserDetails
。现在可以User
通过以下方式访问实例SercurityContextHolder
:
@Override
public User getCurrentAuditor() {
return ((UserAwareUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser();
}
我正在学习springsecurity(基于java的配置),我无法使注销正常工作。当我点击注销时,我看到URL更改为http://localhost:8080/logout并获取“HTTP 404-/logout”。登录功能工作正常(即使使用自定义登录表单),但问题是注销,我怀疑重定向的url“localhost:8080/logout”应该类似于“localhost:8808/springte
在Perl中,使用Moo,可以围绕sub实现sub,它将围绕类中的其他方法。 如何在Raku中实现这种行为,最好使用角色?
我正在尝试实现身份验证 可以请求任何微服务的API网关。 用户微服务-我存储所有用户的地方。实现在此微服务中对用户进行身份验证。按应有的方式工作,登录路由返回我用于在此微服务中对用户进行身份验证的令牌。 其他5个微服务,未经任何身份验证或授权。 问题是:使用身份验证的正确方法是什么
我有一个结构如下的项目。 是我的主要应用程序,而和是导入到Project中的两个库。使用了的一些类,使用了的一些类。 在的文件中,我使用了。一切正常。但是,如果我用替换,它就不能从导入类。它给出错误。
本文向大家介绍如何使用SpringSecurity保护程序安全,包括了如何使用SpringSecurity保护程序安全的使用技巧和注意事项,需要的朋友参考一下 首先,引入依赖: 引入此依赖之后,你的web程序将拥有以下功能: 所有请求路径都需要认证 不需要特定的角色和权限 没有登录页面,使用HTTP基本身份认证 只有一个用户,名称为user 配置SpringSecurity springsecur
问题内容: 在简要回顾了Go语言规范,有效的Go和Go内存模型之后,我仍然不清楚Go通道是如何工作的。 它们是什么样的结构?它们的行为有点像线程安全队列/数组。 它们的实现取决于体系结构吗? 问题答案: 通道的源文件位于/src/pkg/runtime/chan.go中(从您的源代码根目录开始)。 是通道的中央数据结构,带有发送和接收链接列表(持有指向其goroutine和data元素的指针)和一