【问题标题】:How exactly works Spring Security configuration in this Spring Boot project?这个 Spring Boot 项目中的 Spring Security 配置究竟是如何工作的?
【发布时间】:2017-06-03 00:32:23
【问题描述】:

我不太喜欢 Spring Security。我正在开发一个 Spring Boot 项目(实现一些 REST Web 服务),其他人已经实现了 Spring Security 来执行身份验证。它似乎工作正常,但我对它的工作原理(架构)有些怀疑。

所以基本上我有以下课程:

1) User,这是我的模型类,代表一个用户:

@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
}

它是一个休眠类,它提供与 user_user_roles 数据库表的连接,该数据库表包含与特定用户关联的用户 rool 列表(我认为 ROLE_ADMINROLE_USER等)

2) 然后我有 CustomUserDetails 类扩展 User 并实现 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() 构建的,它是代表当前用户角色的字符串)。这个推理对吗?

基本上以前的实现只返回与特定用户相关的GrantedAuthority集合,是吗?

3) CustomUserDetailsS​​ervice 类实现 Spring Security UserDetailsS​​ervice 接口:

@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)) 方法的服务:

  • 首先检索与用户相关的信息(User 对象),包括他的角色列表(List userRoles)。

  • 然后使用这个 User 对象构建之前的 CustomUserDetails 用于检索与用户相关的 GrantedAuthority 的集合。

所有这些推理都正确吗?

然后我还有这个 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 服务安全性。

但是为什么 UserDetailsS​​ervice bean 的自动装配呢?

这个空的 configure() 方法到底是什么?

【问题讨论】:

    标签: java spring spring-mvc spring-boot spring-security


    【解决方案1】:

    你的推理是正确的。

    Spring-security 要求您创建一个实现 UserDetailsS​​ervice 的服务。它期望服务具有返回用户对象的 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' ");
    
    
        }
    

    上面的例子

    • 确保所有请求都经过身份验证和授权。
    • 允许免费访问静态资源
    • 确保 url /admin 只能由具有 ADMIN 角色的用户访问
    • 为身份验证设置基本登录提示
    • 设置注销网址
    • 设置基于 cookie 的 CSRF 令牌系统
    • 设置内容安全策略

    要了解有关所有 spring-security 功能的更多信息,我强烈推荐这些资源。

    【讨论】:

      猜你喜欢
      • 2015-06-10
      • 2022-06-12
      • 2015-06-26
      • 2021-02-22
      • 2015-02-19
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多