5

현재 학교 프로젝트, Spring Boot 백엔드 및 AngularJS 프론트 엔드에 대한 간단한 응용 프로그램을 만들고 있지만 해결할 수없는 보안 문제가 있습니다. .로그인 실패 후 스프링 부트 보안이 Http-Basic-Auth 팝업을 표시합니다.

로깅은 완벽하게 작동하지만 잘못된 비밀번호를 입력하면 기본 로그인 팝업이 표시되어 다소 괴롭습니다. 나는 'BasicWebSecurity'주석을 사용하고 httpBassic을 비활성화 상태로 설정했지만 아무런 결과도 표시하지 않습니다. 즉, 로그인 프로 시저가 더 이상 작동하지 않습니다.

내 보안 클래스 :

package be.italent.security; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.autoconfigure.security.SecurityProperties; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.core.userdetails.UserDetailsService; 
import org.springframework.security.web.csrf.CsrfFilter; 
import org.springframework.security.web.csrf.CsrfToken; 
import org.springframework.security.web.csrf.CsrfTokenRepository; 
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; 
import org.springframework.web.filter.OncePerRequestFilter; 
import org.springframework.web.util.WebUtils; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.http.Cookie; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Autowired 
    public void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService); 
    } 

    @Override 
    public void configure(WebSecurity web){ 
     web.ignoring() 
     .antMatchers("/scripts/**/*.{js,html}") 
     .antMatchers("/views/about.html") 
     .antMatchers("/views/detail.html") 
     .antMatchers("/views/home.html") 
     .antMatchers("/views/login.html") 
     .antMatchers("/bower_components/**") 
     .antMatchers("/resources/*.json"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.httpBasic() 
        .and() 
       .authorizeRequests() 
       .antMatchers("/user", "/index.html", "/", "/projects/listHome", "/projects/{id}", "/categories", "/login").permitAll().anyRequest() 
       .authenticated() 
        .and() 
       .csrf().csrfTokenRepository(csrfTokenRepository()) 
        .and() 
       .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class).formLogin(); 
    } 

    private Filter csrfHeaderFilter() { 
     return new OncePerRequestFilter() { 
      @Override 
      protected void doFilterInternal(HttpServletRequest request, 
              HttpServletResponse response, FilterChain filterChain) 
        throws ServletException, IOException { 
       CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class 
         .getName()); 
       if (csrf != null) { 
        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); 
        String token = csrf.getToken(); 
        if (cookie == null || token != null 
          && !token.equals(cookie.getValue())) { 
         cookie = new Cookie("XSRF-TOKEN", token); 
         cookie.setPath("/"); 
         response.addCookie(cookie); 
        } 
       } 
       filterChain.doFilter(request, response); 
      } 
     }; 
    } 

    private CsrfTokenRepository csrfTokenRepository() { 
     HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
     repository.setHeaderName("X-XSRF-TOKEN"); 
     return repository; 
    } 
} 

는 사람이 나머지를 파괴하지 않고 보여주는에서이 팝업을 방지하는 방법에 대한 아이디어가 있습니까?

솔루션

추가 된이 내 각도 설정에 :

myAngularApp.config(['$httpProvider', 
    function ($httpProvider) { 
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 
    } 
]); 
+0

보안 설정이 다소 혼란스럽게 보입니다. 먼저 httpBasic을 활성화하십시오. 그런 다음 폼 로그인을 사용하고 httpBasic을 비활성화하고자합니다. 나를 위해 명확하지 않은 무엇을 보호하고 싶습니다. AngSS Frontend를 사용하는 것처럼 csrfHeaderFilter가 그 경우입니까? –

+0

젠장, 내가 잘못 복사/붙여 넣기를 했어. 마지막 httpBasic(). disable()은 거기에 있지 않아야합니다. 내 잘못이야! 그것은 실제로 각도 JS 프론트 엔드입니다. – Daemun

+0

확인. 대답은 몇 분 후에 제공 될 것입니다. 바라기를 이것은 바라는 것입니다. 의견이 아니라면 알려주세요. –

답변

13

은의이 문제 그것은 "봄 부팅 보안 팝업"아닙니다

의 브라우저 팝업 시작하자 Spring Boot 앱의 응답에 다음 헤더가 포함 된 경우 표시됩니다.

WWW-Authenticate: Basic 

보안 구성에서 .formLogin()이 나타납니다. 필수 사항은 아닙니다. AngularJS 응용 프로그램에서 양식을 통해 인증하려고하지만 프론트 엔드는 독립적 인 javascript 클라이언트이므로 양식 로그인 대신 httpBasic을 사용해야합니다.

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
      .httpBasic() 
       .and() 
      .authorizeRequests() 
      .antMatchers("/user", "/index.html", "/", "/projects/listHome", "/projects/{id}", "/categories", "/login").permitAll().anyRequest() 
      .authenticated() 
       .and() 
      .csrf().csrfTokenRepository(csrfTokenRepository()) 
       .and() 
      .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class); 
} 

과 같이 이전에 팝업을 언급 한 브라우저의 팝업 처리하는 방법

이 경우에 나타납니다 : 보안 설정이

처럼 보일 수있는 방법을

는 내가이 .formLogin() 제거 스프링 부트 앱의 응답은 WWW-Authenticate: Basic 헤더를 포함합니다. 이것은 당신이 당신의 브라우저에서 API를 매우 쉽게 탐색 할 수있게 해주기 때문에, Spring Boot app의 모든 요청에 ​​대해 이것을 비활성화해서는 안됩니다.

스프링 보안에는 각 요청 내에서 스프링 부트 응용 프로그램에이 헤더를 응답에 추가하지 말도록 지시하는 기본 구성이 있습니다. 이것은 귀하의 요청에 다음과 같은 헤더를 설정하면됩니다 : 당신의 AngularJS와 응용 프로그램에 의해 만들어진 모든 요청에이 헤더를 추가하는 방법

X-Requested-With: XMLHttpRequest 

당신은 단지 응용 프로그램 설정에서 기본 헤더를 추가 할 수 있습니다 같은 것을 :

yourAngularApp.config(['$httpProvider', 
    function ($httpProvider) { 
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 
    } 
]); 

백엔드 이제 (예를 들어 인터셉터가) 당신의 각 응용 프로그램에 의해 처리해야하는 401 응답으로 응답합니다.

예제가 필요한 경우 내 shopping list app을 살펴볼 수 있습니다. 그것 봄 부팅 및 각도 js 이루어집니다.