Spring Boot 및 Spring Security로 REST API를 보호하는 방법은 무엇입니까?


80

REST API 보안이 널리 언급되는 주제라는 것을 알고 있지만 내 기준을 충족하는 작은 프로토 타입을 만들 수 없습니다 (이러한 기준이 현실적인지 확인해야 함). 리소스를 보호하는 방법과 Spring 보안으로 작업하는 방법에는 너무 많은 옵션이 있으므로 내 요구가 현실적인지 명확히해야합니다.

내 요구 사항

  • 토큰 기반 인증 자-사용자는 자격 증명을 제공하고 고유하고 시간이 제한된 액세스 토큰을 얻습니다. 자체 구현에서 토큰 생성, 유효성 확인, 만료를 관리하고 싶습니다.
  • 일부 REST 리소스는 공개되므로 인증 할 필요가 없습니다.
  • 일부 리소스는 관리자 권한이있는 사용자 만 액세스 할 수 있습니다.
  • 모든 사용자에 대한 권한 부여 후에 다른 리소스에 액세스 할 수 있습니다.
  • 기본 인증을 사용하고 싶지 않습니다.
  • Java 코드 구성 (XML 아님)

현재 상태

내 REST API는 매우 잘 작동하지만 이제 보안이 필요합니다. 솔루션을 찾고있을 때 javax.servlet.Filter필터를 만들었습니다 .

  @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        String accessToken = request.getHeader(AUTHORIZATION_TOKEN);
        Account account = accountDao.find(accessToken);

        if (account == null) {    
            throw new UnauthorizedException();    
        }

        chain.doFilter(req, res);

    }

그러나이 솔루션 javax.servlet.filters@ControllerAdviceSpring을 통한 예외 처리에 문제가 있기 때문에 필요에 따라 작동하지 않습니다 servlet dispatcher.

내가 필요한 것

이 기준이 현실적인지 알고 싶고 도움이 필요하며 Spring Security로 REST API 보안을 시작하는 방법을 알고 싶습니다. 많은 튜토리얼 (예 : Spring Data REST + Spring Security )을 읽었 지만 모두 매우 기본적인 구성으로 작동 합니다. 자격 증명을 가진 사용자 는 구성의 메모리저장 되며 DBMS로 작업하고 자체 인증자를 만들어야합니다.

시작하는 방법을 알려주세요.

답변:


67

토큰 기반 인증-사용자는 자격 증명을 제공하고 고유하고 시간이 제한된 액세스 토큰을받습니다. 자체 구현에서 토큰 생성, 유효성 확인, 만료를 관리하고 싶습니다.

실제로 토큰 인증에 필터를 사용하세요.이 경우 가장 좋은 방법입니다.

결국에는 만료 등 Token의 속성을 관리하기 위해 SpringData를 통해 CRUD를 생성 할 수 있습니다.

내 토큰 필터는 다음과 같습니다. http://pastebin.com/13WWpLq2

및 토큰 서비스 구현

http://pastebin.com/dUYM555E

일부 REST 리소스는 공개되므로 인증 할 필요가 없습니다.

문제가되지 않습니다. 다음과 같이 Spring 보안 구성을 통해 리소스를 관리 할 수 ​​있습니다. .antMatchers("/rest/blabla/**").permitAll()

일부 리소스는 관리자 권한이있는 사용자 만 액세스 할 수 있습니다.

@Secured수업 에 대한 주석을 살펴보십시오 . 예:

@Controller
@RequestMapping(value = "/adminservice")
@Secured("ROLE_ADMIN")
public class AdminServiceController {

다른 리소스는 모든 사용자에 대한 권한 부여 후에 액세스 할 수 있습니다.

Spring Security 구성으로 돌아가서 다음과 같이 URL을 구성 할 수 있습니다.

    http
            .authorizeRequests()
            .antMatchers("/openforall/**").permitAll()
            .antMatchers("/alsoopen/**").permitAll()
            .anyRequest().authenticated()

기본 인증을 사용하고 싶지 않습니다.

네, 토큰 필터를 통해 사용자가 인증됩니다.

Java 코드 구성 (XML 아님)

위의 단어로 돌아가서를보세요 @EnableWebSecurity. 수업은 다음과 같습니다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

구성 방법 을 재정의해야 합니다 . 예를 들어 아래 코드는 매처를 구성하는 방법입니다. 다른 프로젝트에서 가져온 것입니다.

    @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/assets/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .loginPage("/login")
                .defaultSuccessUrl("/", true)
                .successHandler(customAuthenticationSuccessHandler)
                .permitAll()
            .and()
                .logout()
                .logoutUrl("/logout")
                .invalidateHttpSession(true)
                .logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .and()
                .csrf();
}

제 질문에 제발 도와 주 시겠어요? stackoverflow.com/questions/46065063/…
Felipe A.

2
모든 요구 사항을 포함하는 예제 프로젝트가 있습니까?
AlikElzin-kilaka

@Oleksandr : 긴 샷이지만 RESTAuthenticationTokenProcessingFilter 클래스의 updateLastLogin (...) 메서드에서 스레드를 시작한 이유를 말씀해 주시겠습니까?
Z3d4s

1
@ z3d4s, 실제로는 오래된 예 (4 년)입니다. 지금은 OffsetDateTime, 다른 접근 방식 등을 사용하는 것이 좋습니다 :) 저장하는 동안 추가 시간이 걸릴 수 있으므로 사용자 요청에 대한 처리 시간을 줄이기 위해 사용하도록 제안한 새 스레드 데이터베이스에.
Oleksandr Loushkin

아, 알겠습니다. 천재적인 솔루션입니다! 감사!
Z3d4s

4

Spring 보안은 REST URL에 대한 인증 및 권한 부여에도 매우 유용합니다. 사용자 지정 구현을 지정할 필요가 없습니다.

먼저 아래와 같이 보안 구성에서 restAuthenticationEntryPoint에 대한 entry-point-ref를 지정해야합니다.

 <security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" >

    <security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/>
    <security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
</security:http>

restAuthenticationEntryPoint에 대한 구현은 다음과 같습니다.

 @Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

   public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException {
      response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
   }
}

그런 다음 RequestHeaderAuthenticationFilter를 지정해야합니다. RequestHeader 키를 포함합니다. 이것은 기본적으로 사용자의 인증을 식별하는 데 사용됩니다. 일반적으로 RequestHeader는 REST 호출을 수행하는 동안이 정보를 전달합니다. 예를 들어 아래 코드를 고려하십시오.

   <bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    <property name="principalRequestHeader" value="Authorization"/>
    <property name="authenticationManager" ref="authenticationManager" />
  </bean>

여기,

<property name="principalRequestHeader" value="Authorization"/>

"Authorization"은 들어오는 요청을 표시하는 키입니다. 필요한 사용자의 인증 정보를 보유합니다. 또한 요구 사항을 충족하려면 PreAuthenticatedAuthenticationProvider를 구성해야합니다.

   <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
  <bean id="userDetailsServiceWrapper"
      class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <property name="userDetailsService" ref="authenticationService"/>
  </bean>
</property>
</bean>

이 코드는 사용자 지정 구현없이 인증 및 권한 부여를 통해 REST URL을 보호하는 데 사용됩니다.

전체 코드는 아래 링크를 참조하십시오.

https://github.com/srinivas1918/spring-rest-security



-1

REST API의 유효성을 검사하려면 두 가지 방법이 있습니다.

1-application.properties 파일에 설정된 기본 사용자 이름 및 비밀번호를 사용하는 기본 인증

기본 인증

2-실제 사용자 이름 및 비밀번호로 데이터베이스 (userDetailsService)를 사용하여 인증

고급 인증


동영상이 유용합니다. ReST API에 대해 동일한 고급 인증을 수행하는 방법. 여기에서는 웹에 대해서만 설명합니다. REST API의 고급 인증에 대한 비디오 튜토리얼이 있습니까?
Jacob

두 번째 영상 (고급 인증)을 본다면 REST 클라이언트 (REST API 용)를 사용하여 동일한 인증을하고 있습니다.
jeet singh parmar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.