我并非如此 Spring Security 。我正在开发一个 Spring Boot 项目(实现一些REST Web服务),其他人已经实现了Spring Security来执行身份验证。它似乎工作正常,但我对它是如何工作(架构)有一些疑问。
所以基本上我有以下课程:
1)用户,即代表用户的模型类:
@Entity
@Table(name = "user",
uniqueConstraints = {
@UniqueConstraint(columnNames = {"email","username"})
})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//@Pattern(regexp="\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b",flags = Pattern.Flag.CASE_INSENSITIVE)
@Column(name="email", unique=true,nullable=false)
private String email;
@NotNull
@Column(name="registration_date",nullable=false)
private Date registration_date;
@NotBlank
@Column(name="username",nullable = false,unique=true)
private String username;
@NotBlank
@Column(name="password",nullable = false)
private String password;
@Column(name="enabled", nullable = false)
private boolean enabled;
@ManyToMany
@JoinTable(name = "user_user_roles", joinColumns = {
@JoinColumn(name = "id_user", updatable = true) },
inverseJoinColumns = { @JoinColumn(name = "id_roles",
updatable = true)},
uniqueConstraints={@UniqueConstraint(columnNames = {"id_user","id_roles"})}
)
@Cascade({CascadeType.DETACH,CascadeType.MERGE,CascadeType.REFRESH,CascadeType.PERSIST,
CascadeType.SAVE_UPDATE})
private List<UserRole> userRoles;
// CONSTRUCTOR, GETTER AND SETTER METHODS
}
这是一个hibernate类,它提供了 user_user_roles 数据库表的连接,其中包含与特定用户关联的用户rool列表(我认为 ROLE_ADMIN , ROLE_USER ,etcetc)
2)然后我有 CustomUserDetails 类,扩展用户并实现Spring Security UserDetails 界面。
因此,它意味着将包含与特定用户相关的所有信息(其中包含与此用户关联的角色),并实现 UserDetails 界面中声明的所有方法。
public class CustomUserDetails extends User implements UserDetails {
private static final long serialVersionUID = 1L;
public CustomUserDetails(User user){
super(user);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for(UserRole role : this.getUserRoles() ){
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName());
authorities.add(grantedAuthority);
}
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getUsername() {
return super.getUsername();
}
}
在我看来,这个类代表了Spring应用程序和Spring Security之间的桥梁(类似的东西带有与特定用户相关的角色信息,是吗?)。
在此课程中,与用户角色列表相关的信息包含在扩展 GrantedAuthority 的通用对象集合中。
我认为 GrantedAuthority 对象代表用户的角色(实际上是由 role.getName()构建的,这是表示当前用户角色的字符串)。这个推理是否正确?
基本上,prvious实现只返回与特定用户相关的 GrantedAuthority 集合,是吗?
3)实现Spring Security UserDetailsService 界面的 CustomUserDetailsService 类:
@Transactional
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
@Autowired
private UserDAO userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("No user present with username: "+username);
}else{
return new CustomUserDetails(user);
}
}
}
基本上这是一个只实现 loadUserByUsername(String username))方法的服务:
首先检索与用户相关的信息(用户对象),包括他的角色列表(列出userRoles )。
然后使用此用户对象构建之前用于检索与用户相关的 GrantedAuthority 集合的 CustomUserDetails 。
所有这些推理都是正确的吗?
然后我还有 WebSecurityConfig 我认为代表 Spring Security 配置:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
@EnableAutoConfiguration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
这对我来说非常有用。究竟是什么?
据我所知,它是通过** @EnableWebSecurity **启用REST Web服务安全性。
但为什么 UserDetailsService bean的自动装配?
究竟是什么阻碍了这个空的 configure()方法?
答案 0 :(得分:4)
你的推理是正确的。
Spring-security要求您创建实现 UserDetailsService 的服务。它希望服务具有 loadUserByUsername 方法,该方法返回用户对象(需要实现Spring的 User 类)。此用户实例用于获取权限,以便您可以限制对某些URL的访问。即,您可以将URL访问映射到具有特定权限的用户。
就空方法configure()而言,它用于对URL进行身份验证和授权(如上所述)以及更多内容。事实上,就安全性而言,这是最灵活的。有效的方法。
我的项目的配置方法如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/static/**").permitAll()
.mvcMatchers("/admin").access("hasAuthority('ROLE_ADMIN')")
.mvcMatchers("/employees").access("hasAuthority('ROLE_STAFF')")
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.logout().logoutSuccessUrl("/")
.and()
.headers().contentSecurityPolicy("default-src 'self' " +
"https://ajax.googleapis.com " +
"https://cdnjs.cloudfare.com " +
"style-src 'self' 'unsafe-inline' ");
}
上面的例子
要了解有关所有弹簧安全功能的更多信息,我强烈推荐这些资源。