使用fetch API

时间:2016-09-24 22:30:00

标签: java ajax spring spring-boot

我正在关注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存储库进行交互而无需额外的安全配置?

1 个答案:

答案 0 :(得分:0)

问题的根源是fetch()默认情况下不发送Cookie。所以我应该添加credentials: 'include'来请求选项对象:

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

references