春季安全跨源

时间:2019-12-06 21:10:48

标签: java spring spring-boot security

我开发了REST API。除了安全性(登录,获取登录用户等)之外,其他所有东西都运行良好 当我登录用户并尝试通过 / getWhoAmI 端点获取它时,我无法获取它(它返回 HttpStatus.NOT_FOUND ,因为没有身份验证)。在邮递员中,效果很好!

我执行以下情形:登录用户,然后通过/ getWhoAmI获得它。在邮递员中,它可以工作并返回登录的用户,但是在我的JavaScript应用程序中,它返回HttpStatus.NOT_FOUND。

此外,我尝试调试它,并在 getWhoAmI 中,身份验证为 null (仅当我使用JavaScript调用时, ,在邮递中)包含已验证的用户)

这是 / getWhoAmI 端点

@GetMapping(path = "/getWhoAmI")
public ResponseEntity<UserModel> getWhoAmI(Authentication authentication) {

    // if there is no authenticated user
    if(authentication == null) {
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
    UserModel loggedUser = userRepo.findByUsername(loggedUsername);

    return new ResponseEntity<>(loggedUser, HttpStatus.OK);
}

这是我的 SecurityConfig

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    private ApplicationUserDetailsService userDetailsService;

    public SecurityConfig(ApplicationUserDetailsService userDetailService) {
        this.userDetailsService = userDetailService;
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").permitAll()
        .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
        .and().logout().logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))) // return HttpStatus.OK after successfull logout
        .and().csrf().disable();
        http.headers().frameOptions().disable();
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.userDetailsService(userDetailsService);
    }

}

登录端点:

@PostMapping(path = "/login")
public ResponseEntity<UserModel> login(
        @RequestParam(value = "username") String username, 
        @RequestParam(value = "password") String password) {

    UserModel user = userRepo.findUserByUsernameAndPassword(username, password);

    if(user != null) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());

        if(userDetails != null) {
            Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            System.out.println(authentication);
        }

        return new ResponseEntity<>(user, HttpStatus.OK);
    }

    return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}

我的前端JavaScript:

$.ajax({
    method: "GET",
    url: SERVER_URL + "/getWhoAmI",
    complete: function(data) {
        console.log(data.responseJSON);
    }
});

1 个答案:

答案 0 :(得分:2)

基于交换的评论:

由于来自前端的调用是跨域请求(CORS),因此ajax调用未发送会话标识符cookie(JSESSIONID)。

对于跨站点请求,必须将XMLHttpRequest.withCredentials标志设置为true,以包括cookie和授权标头之类的凭据。

对于JQuery的ajax函数,可以用xhrFields: { withCredentials: true }完成。 axios具有类似的withCredentials标志。