【问题标题】:Sending credentials in secured spring-boot application using fetch API使用 fetch API 在安全的 spring-boot 应用程序中发送凭据
【发布时间】:2016-09-24 22:29:59
【问题描述】:

我正在关注this 教程,唯一的区别是我使用Fetch API 来查询 REST 存储库。我的问题是,在成功授权后,每个 fetch() 调用都会返回包含登录表单 html 字符串的响应。具体来说,这种代码

fetch(`${root}/employees?size=${pageSize}`).then( p => p.json()})

在 Chrome 控制台中产生以下错误:

localhost/:1 Uncaught (in promise) SyntaxError: Unexpected token < in
JSON at position 0

如果我向fetch 添加一个带有授权的标头:

fetch(`${root}/employees?size=${pageSize}`, {
  method: 'GET',
  headers: new Headers({'Content-Type': 'application/json',
             'Authorization': 'Basic '+btoa('greg:turnquist'))})

一切正常,但在配置Spring Security beans 并且肯定这不是最佳实践之后,这看起来很愚蠢。

所有 java 源代码与教程中的相同,但我在此处包含来自配置类的片段:

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private SpringDataJpaUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(this.userDetailsService)
                .passwordEncoder(Manager.PASSWORD_ENCODER);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/build/**", "/main.css").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .defaultSuccessUrl("/", true)
                .permitAll()
                .and()
            .httpBasic()
                .and()
            .csrf().disable()
            .logout()
                .logoutSuccessUrl("/");
    }

}

SpringDataJpaUserDetailsService.java

@Component
public class SpringDataJpaUserDetailsService implements UserDetailsService {

    private final ManagerRepository repository;

    @Autowired
    public SpringDataJpaUserDetailsService(ManagerRepository repository) {
        this.repository = repository;
    }

    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
        Manager manager = this.repository.findByName(name);
        return new User(manager.getName(), manager.getPassword(),
                AuthorityUtils.createAuthorityList(manager.getRoles()));
    }

}

EmployeeRepository.java

@PreAuthorize("hasRole('ROLE_MANAGER')")
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {

    @Override
    @PreAuthorize("#employee?.manager == null or #employee?.manager?.name == authentication?.name")
    Employee save(@Param("employee") Employee employee);

    @Override
    @PreAuthorize("@employeeRepository.findOne(#id)?.manager?.name == authentication?.name")
    void delete(@Param("id") Long id);

    @Override
    @PreAuthorize("#employee?.manager?.name == authentication?.name")
    void delete(@Param("employee") Employee employee);

}

所以我的问题是如何使用新的javascript fetch API 从授权页面发送凭据以与 REST 存储库交互而无需额外的安全配置?

【问题讨论】:

    标签: java ajax spring spring-boot


    【解决方案1】:

    问题的根源在于fetch() 默认不发送cookies。所以我应该在请求选项对象中添加credentials: 'include':

    fetch(`${root}/employees?size=${pageSize}`, {
      method: 'GET',
      credentials: 'include'})
    

    references

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-09
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 2018-07-22
      • 1970-01-01
      • 2015-10-10
      • 2022-06-11
      相关资源
      最近更新 更多