spring-security 使用HTTP标头的Spring安全性

2ic8powd  于 2022-11-11  发布在  Spring
关注(0)|答案(4)|浏览(218)

我正在尝试为我的Sping Boot 应用程序添加安全性。我当前的应用程序使用REST控制器,每次收到GETPOST请求时,我都会读取HTTP头来检索用户和密码,以便根据我存储的所有用户的属性文件来验证它们。我想将其更改为使用Spring Security,这是我目前得到的结果:

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/swagger-ui.html").hasRole("ADMIN")
            .anyRequest().authenticated();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("admin").password("password").roles("ADMIN").build());
    }
}

我如何告诉configure方法将从头部而不是登录表单中检索用户凭据?

izj3ouym

izj3ouym1#

最少的代码添加是定义一个筛选器并将其添加到安全配置中,如smth

XHeaderAuthenticationFilter.java文件系统

@Component
public class XHeaderAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String xAuth = request.getHeader("X-Authorization");

        User user = findByToken(xAuth);

        if (user == null) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token invalid");
        } else {
            final UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);

            filterChain.doFilter(request, response);
        }
    }

    //need to implement db user validation...
    private User findByToken(String token) {
        if (!token.equals("1234"))
            return null;

        final User user = new User(
                "username",
                "password",
                true,
                true,
                true,
                true,
                Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));

        return user;
    }
}

安全配置.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(final HttpSecurity http) throws Exception {
            http.sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .exceptionHandling()
                    .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                .and()
                .addFilterBefore(new XHeaderAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
}

另一种方法是使用spring的AOP来定义在进入带注解的控制器方法之前要执行的某些逻辑的注解

3bygqnnd

3bygqnnd2#

您应该避免使用默认的org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter,因为它从您的请求参数中获取客户端提供的用户名和密码,而您实际上需要从头部获取它们。
因此,您应该编写一个自定义的AuthenticationFilter扩展引用的UsernamePasswordAuthenticationFilter,以更改其行为来满足您的要求:

public class HeaderUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

  public HeaderUsernamePasswordAuthenticationFilter() {
    super();
    this.setFilterProcessesUrl("/**");
    this.setPostOnly(false);
  }

  /* (non-Javadoc)
   * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainPassword(javax.servlet.http.HttpServletRequest)
   */
  @Override
  protected String obtainPassword(HttpServletRequest request) {
    return request.getHeader(this.getPasswordParameter());
  }

  /* (non-Javadoc)
   * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainUsername(javax.servlet.http.HttpServletRequest)
   */
  @Override
  protected String obtainUsername(HttpServletRequest request) {
    return request.getHeader(this.getPasswordParameter());
  }

}

此筛选器示例扩展org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter侦听每个请求,并从标头而不是parameters获取usernamepassword
然后,您应该按照以下方式更改配置,将滤波器设置在UsernamePasswordAuthenticationFilter位置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.addFilterAt(
                new HeaderUsernamePasswordAuthenticationFilter(), 
                UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/swagger-ui.html").hasRole("ADMIN")
            .anyRequest().authenticated();

}
ergxz8rk

ergxz8rk3#

内存中的身份验证可以满足您的目的

@Configuration
@EnableWebMvc
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("user1").password("password1").roles("USER")
        .and()
        .withUser("user2").password("password2").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().fullyAuthenticated();
        http.httpBasic();   
    }

}
wr98u20j

wr98u20j4#

在Sping Boot 应用程序中,您可以将以下内容添加到application.properties

security.user.name=user
security.user.password=password

它将完成其余的工作,如从标题和验证中获取信息,请访问https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html

相关问题