복붙노트

[SPRING] 기본 인증 공급자와 함께 Spring-Security PasswordEncoder 사용?

SPRING

기본 인증 공급자와 함께 Spring-Security PasswordEncoder 사용?

나는 Spring 4.0.8 RELEASE와 Spring-Security 3.2.5 RELEASE를 사용하고있다.

등록 된 사용자 만 액세스 할 수있는 HTTP 다이제스트를 사용하여 REST WebService를 구축하고 있습니다.

내 web.xml은 다음과 같습니다.

<servlet>
    <servlet-name>rest</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>rest</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>


<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

applicationContext.xml에는 내 컨트롤러 / DAO가 포함되어 있습니다.

<import resource="security-context.xml" />

<bean id="daoPersonal" class="com.test.dao.PersonalDAO">
    <property name="dataSource" ref="dataSource" />
</bean>

이제 security-context.xml은 다음과 같습니다.

 <?xml version="1.0" encoding="UTF-8"?>
 <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
         http://www.springframework.org/schema/beans     
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <debug />
    <http entry-point-ref="digestEntryPoint">
        <headers />
        <intercept-url pattern="/**" access="ROLE_USER" />
        <custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
    </http>

    <beans:bean id="digestFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
        <beans:property name="userDetailsService" ref="daoPersonal" />
        <beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
    </beans:bean>

    <beans:bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
        <beans:property name="realmName" value="Contacts Realm via Digest Authentication" />
        <beans:property name="key" value="acegi" />
    </beans:bean>

    <beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

    <authentication-manager>
        <authentication-provider user-service-ref="daoPersonal">
             <password-encoder ref="bcryptEncoder" />
        </authentication-provider>
    </authentication-manager>
 </beans:beans>

내 PersonalDAO

 public class PersonalDAO extends NamedParameterJdbcDaoSupport implements UserDetailsService  {

 /*my other code
  ...
 */

 @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println(new Date() + " PersonalDAO loadUserByUsername: " + username);
         List<UserDetails> users = getJdbcTemplate().query(USER_QUERY, new String[] {username}, new RowMapper<UserDetails>() {
                public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                    String username = rs.getString(1);
                    String password = rs.getString(2);
                    boolean enabled = true;
                    Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
                    auths.add(new SimpleGrantedAuthority("ROLE_USER"));
                    return new User(username, password, enabled, true, true, true, auths);
                }
            });
         if(users.size()==0){
             throw new UsernameNotFoundException("");
         }
         System.out.println(new Date() + "Users Found: " + users.size());
         return users.get(0);
    }
 }

인증 공급자 안에 암호 부호기가 없으면 데이터베이스의 일반 텍스트 암호를 사용하여 의도 한대로 작동합니다. 그러나 암호 인코더 (및 db의 암호가 bcrypt로 변경된 암호로 바뀜)를 사용하면 브라우저에 로그인이 잘못되어 다시 묻는 메시지가 표시됩니다. 필자는 PersonalDAO가 호출되어 사용자를 찾은 것을 확인할 수 있습니다.

나는 여전히 나의 암호를 가지고있는 나의 데이터베이스에 또 다른 사용자를 가지고있다. 나는 bcryptencoder가 활성화 된 상태에서 여전히 내 서버 로그에 다음과 같이 로그인을 시도했다.

 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder matches
 WARNING: Encoded password does not look like BCrypt

이제 적어도 BCryptEncoder가 호출되었음을 알 수 있지만, 인코딩 된 것을 의미하는 일치가 발생하고 여전히 들어갈 수 없습니다 (예상 될 수 있음).

내가 뭘 놓치고 있니?

편집하다:

로그 아웃풋이 많지는 않지만 여기에 있습니다 :

Fri Dec 05 15:07:06 CET 2014 PersonalDAO loadUserByUsername: test
Fri Dec 05 15:07:06 CET 2014 Users Found: 1

db의 암호화 된 암호 :     2 달러 2a 달러 10 달러

해결법

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

    1.HTTP 다이제스트 인증과 BCrypt 암호 엔코더의 조합은 불가능합니다. 이는 HTTP 다이제스트 알고리즘이 비밀번호가 일반 텍스트로 저장되어야하기 때문입니다. 인증 방법을 변경하거나 암호 인코딩을 제거해야합니다.

    HTTP 다이제스트 인증과 BCrypt 암호 엔코더의 조합은 불가능합니다. 이는 HTTP 다이제스트 알고리즘이 비밀번호가 일반 텍스트로 저장되어야하기 때문입니다. 인증 방법을 변경하거나 암호 인코딩을 제거해야합니다.

  2. from https://stackoverflow.com/questions/27317368/using-spring-security-passwordencoder-with-default-authentication-provider by cc-by-sa and MIT license