복붙노트

[SPRING] 스프링 보안 : REST 인증 테스트 및 이해

SPRING

스프링 보안 : REST 인증 테스트 및 이해

Security-application-context.xml :

<!-- Global Security settings -->
<security:global-method-security pre-post-annotations="enabled" />
<security:http pattern="/resources/**" security="none"/>

<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
    <security:form-login login-page="/login" default-target-url="/canvas/list" always-use-default-target="false" authentication-failure-url="/denied.jsp" />
    <security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService" token-validity-seconds="1209600" data-source-ref="dataSource"/>
    <security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<!--<security:intercept-url pattern="/**" requires-channel="https"/>-->
<security:port-mappings>
    <security:port-mapping http="8080" https="8443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
</security:http>

<!-- Rest authentication, don't edit, delete, add-->
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

<security:filter-chain-map path-type="ant">
    <security:filter-chain filters="persistencefilter,authenticationfilter" pattern="/login"/>
    <security:filter-chain filters="persistencefilter,logoutfilter" pattern="/logout"/>
    <security:filter-chain pattern="/rest/**" filters="persistencefilter,restfilter" />
</security:filter-chain-map>
</bean>

<bean id="persistencefilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

<bean id="authenticationfilter" class="com.journaldev.spring.utility.AuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
    <property name="passwordParameter" value="pass"/>
    <property name="usernameParameter" value="user"/>
    <property name="postOnly" value="false"/>
</bean>

<bean id="myAuthSuccessHandler" class="com.journaldev.spring.utility.AuthenticationSuccessHandler"/>

<bean id="myLogoutHandler" class="com.journaldev.spring.utility.MyLogoutHandler"/>

<bean id="logoutfilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg index="0" value="/"/>
    <constructor-arg index="1">
        <list>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
            <bean id="myLogoutHandler" class="com.journaldev.spring.utility.MyLogoutHandler"/>
        </list>
    </constructor-arg>
</bean>

<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
        <list>
            <ref bean="roleVoter"/>
        </list>
    </property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>

<bean id="restfilter" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
    <property name="securityMetadataSource">
        <security:filter-invocation-definition-source>
            <security:intercept-url pattern="/rest/**" access="ROLE_USER"/>
        </security:filter-invocation-definition-source>
    </property>
</bean>
<!-- Rest authentication ends here-->

<!-- queries to be run on data -->
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:property name="key" value="_spring_security_remember_me" />
    <beans:property name="tokenRepository" ref="jdbcTokenRepository"/>
    <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
</beans:bean>

<!--Database management for remember-me -->
<beans:bean id="jdbcTokenRepository"
            class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
    <beans:property name="createTableOnStartup" value="false"/>
    <beans:property name="dataSource" ref="dataSource" />
</beans:bean>

<!-- Remember me ends here -->
<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider user-service-ref="LoginServiceImpl">
       <security:password-encoder  ref="encoder"/>
    </security:authentication-provider>
</security:authentication-manager>

<beans:bean id="encoder"
            class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="11" />
</beans:bean>

<beans:bean id="daoAuthenticationProvider"
            class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
            <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
           <beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>

AuthenticationFilter :

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter{

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request,HttpServletResponse response){
        return (StringUtils.hasText(obtainUsername(request)) && StringUtils.hasText(obtainPassword(request)));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException{
        System.out.println("Successfule authenticaiton");
        super.successfulAuthentication(request,response,chain,authResult);
        chain.doFilter(request,response);

    }
}

AuthenticationSuccessHandler :

public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{

    @PostConstruct
    public void afterPropertiesSet(){
        setRedirectStrategy(new NoRedirectStrategy());
    }

    protected class NoRedirectStrategy implements RedirectStrategy{

        @Override
        public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
            // Checking redirection issues
        }
    }
}

MyLogoutHandler :

public class MyLogoutHandler implements LogoutHandler {

     @Override
    public void logout(HttpServletRequest request,HttpServletResponse response,Authentication authentication){

     }
}

LoginServiceImpl :

@Transactional
@Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{

    @Autowired private PersonDAO personDAO;
    @Autowired private Assembler assembler;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        Person person = personDAO.findPersonByUsername(username.toLowerCase());
            if(person == null) { throw new UsernameNotFoundException("Wrong username or password");} 
        return assembler.buildUserFromUserEntity(person);
    }

    public LoginServiceImpl() {
    }
}

아래의 Curl을 사용하여 시도했지만 매회 302 번을 얻습니다. 내가 원했던 것은 인증을 성공했는지 여부에 따라 쿠키를 얻는 것입니다.

akshay@akshay-desktop:~/Downloads/idea136/bin$ curl -i -X POST -d j_username=email@email.de -d j_password=password -c /home/cookies.txt http://localhost:8080/j_spring_security_check 
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=7F7B5B7056E75C138E550C1B900FAB4B; Path=/; HttpOnly
Location: http://localhost:8080/canvas/list
Content-Length: 0
Date: Thu, 26 Mar 2015 15:33:21 GMT

akshay@akshay-desktop:~/Downloads/idea136/bin$ curl -i -X POST -d j_username=email@email.de -d j_password=password -c /home/cookies.txt http://localhost:8080/j_spring_security_check 
HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=BB6ACF38F20FE962924103DF5F419A55; Path=/; HttpOnly
Location: http://localhost:8080/canvas/list
Content-Length: 0
Date: Thu, 26 Mar 2015 15:34:02 GMT

필요한 것이 있으면 친절하게 알려주십시오. 고마워.

해결법

  1. ==============================

    1.302를 얻고 쿠키를 저장 한 후 Curl 명령을 사용해보십시오.

    302를 얻고 쿠키를 저장 한 후 Curl 명령을 사용해보십시오.

    curl -i --header "Accept : application / json"-X GET -b /home/cookies.txt http : // localhost : 8080 /

    희망이 도움이

  2. ==============================

    2.REST 엔드 포인트 로그인에 브라우저 및 HTTP 기본 인증으로 로그인 할 때 양식 기반 로그인을 사용할 수 있습니다. xml 구성의 경우, 각각과 같을 것입니다.

    REST 엔드 포인트 로그인에 브라우저 및 HTTP 기본 인증으로 로그인 할 때 양식 기반 로그인을 사용할 수 있습니다. xml 구성의 경우, 각각과 같을 것입니다.

    동일을위한 스프링 문서

  3. ==============================

    3.우리는 보그 야? REST URL에 대한 http 401 요청을 받습니까? 브라우저에서 URL을 입력하고 로그인 ID와 비밀번호를 묻는 팝업이 표시되는지 확인하십시오.

    우리는 보그 야? REST URL에 대한 http 401 요청을 받습니까? 브라우저에서 URL을 입력하고 로그인 ID와 비밀번호를 묻는 팝업이 표시되는지 확인하십시오.

    Java 클라이언트를 사용하여 테스트하는 경우 아래에 표시된 것처럼 클라이언트 코드에서 기본 인증 헤더를 설정할 수 있습니다.

    CredentialsProvider provider = new BasicCredentialsProvider();
    UsernamePasswordCredentials credentials = new     UsernamePasswordCredentials("user1", "user1Pass");
    provider.setCredentials(AuthScope.ANY, credentials);
    HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
    
    HttpResponse response = client.execute(new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
    int statusCode = response.getStatusLine().getStatusCode();
    assertThat(statusCode, equalTo(HttpStatus.SC_OK));
    
  4. from https://stackoverflow.com/questions/29276806/spring-security-testing-understanding-rest-authentication by cc-by-sa and MIT license