web-dev-qa-db-ja.com

Spring Security:DBおよびapplicationContextのパスワードエンコーディング

設定があります(applicationContext-security.xml):

<authentication-manager alias="authenticationManager">
    <authentication-provider>
    <password-encoder hash="sha"/>
        <jdbc-user-service data-source-ref="dataSource"/>
    </authentication-provider>
</authentication-manager>

反対側から私のdataSource(それは JdbcDaoImpl )からのSQLを持っています:

...
    public static final String DEF_USERS_BY_USERNAME_QUERY =
            "select username,password,enabled " +
            "from users " +
            "where username = ?";
...

このコードにはshaに関するWordがあるため、標準のSpring Security usersテーブルから選択されたパスワードはエンコードされません。

おそらく、ここで休止状態のマッピング設定のsha列にいくつかのpassword属性を提供する必要があります。

<class name="model.UserDetails" table="users">
    <id name="id">
        <generator class="increment"/>
    </id>
    <property name="username" column="username"/>
    <property name="password" column="password"/>
    <property name="enabled" column="enabled"/>
    <property name="mail" column="mail"/>
    <property name="city" column="city"/>
    <property name="confirmed" column="confirmed"/>
    <property name="confirmationCode" column="confirmation_code"/>

    <set name="authorities" cascade="all" inverse="true">
        <key column="id" not-null="true"/>
        <one-to-many class="model.Authority"/>
    </set>

</class>

現時点では、パスワードはそのままDBに保存されていますが、エンコードする必要があります。

applicationContext configとDBクエリを同じパスワードエンコーディングにするにはどうすればよいですか?

33
sergionni

すでにハッシュされたパスワードが含まれている既存のデータベースを使用してアプリを構築するのではなく、自分でハッシュシステムを選択する場合は、ハッシュアルゴリズムでもソルトを使用するようにしてください。単なるダイジェストを使用しないでください。

適切な選択はbcryptです。これは、Spring Security 3.1でBCryptPasswordEncoderjBCrypt を使用して実装)を介して直接サポートされるようになりました。これにより、ソルトが自動的に生成され、単一の文字列内のハッシュ値と連結されます。

一部のデータベースには、ハッシュのサポートが組み込まれています(例: Postgres )。それ以外の場合、パスワードをJDBCに渡す前に自分でパスワードをハッシュする必要があります。

String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);

ユーザーを作成するときにパスワードをエンコードするために必要なことはこれだけです。

認証には、次のようなものを使用します。

<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

<bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <property name="userDetailsService" ref="yourJdbcUserService" />
  <property name="passwordEncoder" ref="encoder" />
</bean>
77
Shaun the Sheep

受け入れられた答えに関するもう少しの説明。それが誰かを助けることを願っています。

データベースに入力する前にパスワードを自分でハッシュします。

String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);

BCryptPasswordEncoder Beanをsecurity-config.xmlに追加します

PasswordEncoderをプロパティとして認証プロバイダークラスに追加します。自動配線するか、setterメソッドとgetterメソッドを提供します。

@AutoWired
private BCryptPasswordEncoder passwordEncoder;

ログインのためにユーザーを認証している間にプロパティを取得します

<bean id="dbAuthenticationProvider" class="mypackage.auth.spring.DBAuthenticationProvider" >
    <property name="dataSource" ref="routingDataSource"></property>
    <property name="passwordEncoder" ref="encoder" />
    <property name="passwordQuery"
        value="select password as password from tbl where username=:username">
    </property> 
</bean>

そして、認証クラスでは両方のパスワードが一致します

 new BCryptPasswordEncoder().matches(plainTextPasswdFromUserInput, hashedPasswdFromDb)
8
false9striker

Spring Security 3.1を使用して、これを試してください:

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="service">
        <password-encoder hash="sha"/>
        <jdbc-user-service data-source-ref="dataSource"/>
    </authentication-provider>
</authentication-manager>

<beans:bean id="dataSource" ...>
    ...
</beans:bean>

<beans:bean id="service" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource"/>
        ...
</beans:bean>

新機能:authentication-providerserviceを指し、servicedatasourceを指します。

Edit:Javaでは、次のようなものでパスワードをエンコードする必要があります。

DigestUtils.sha(request.getParameter("password"));

警告:注意してください! [〜#〜] sha [〜#〜]MD5を混在させないでください!

password-encoderauthentication-provider[〜#〜] sha [〜#〜]として設定する場合、Java一貫性を保つための同じ方法。ただし、JavaにMD5として含める場合、見つかったサンプルのように、hash「md5」に。 DigestUtils は、md5エンコーダーも提供します。

DigestUtils.md5(request.getParameter("password"));
5
falsarella

簡単な方法でapplicationContext-security.xmlのようなことができます

<authentication-manager alias="authenticationManager">
   <authentication-provider>
    <password-encoder ref="encoder"/>
    <jdbc-user-service data-source-ref="dataSource"
       users-by-username-query="
          select username,password, enabled 
          from principal where username=?" 
       authorities-by-username-query="
          select p.username, a.authority from principal p, authority a
          where p.id = a.principal_id and p.username=?" 
    />
   </authentication-provider>
</authentication-manager> 

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

Javaで

public static String encodePasswordWithBCrypt(String plainPassword){
    return new BCryptPasswordEncoder().encode(plainPassword);
}

その後、テストします

System.out.println(encodePasswordWithBCrypt("fsdfd"));
5
user2368100

アノテーションでそれを行うためのヒント

@Configuration
@EnableWebSecurity
@PropertySource("classpath://configs.properties")
public class SecurityContextConfig extends WebSecurityConfigurerAdapter {


@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
}


@Bean(name = "passwordEncoder")
public PasswordEncoder getPasswordEncoder(){
    return new BCryptPasswordEncoder();     
 }

}
4
Alireza Fattahi

受け入れられた答えは正しい。 spring 3.1およびBCryptエンコードアルゴリズムでテストしました。

ユーザーを作成するとき。

PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword()));
userDao.save(userEntity);

ユーザーがログインするときは、覚えて、プレーンパスワードを使用してください(ハッシュ化されていない)。と同じように:

Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);

Security-configは次のとおりです。

    <bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userService" />
        <property name="hideUserNotFoundExceptions" value="false" />
        <property name="passwordEncoder" ref="encoder" />
    </bean>

それが誰かを助けることを願っています!

2
maoyang

3.1.xでは、このマッピングは認証に対して機能しません。作業方法は次のとおりです。

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

<authentication-manager>
  <authentication-provider user-service-ref="userDetailsService">
          <password-encoder ref="bCryptPasswordEncoder"/>
  </authentication-provider>
</authentication-manager>
1
z0mb1ek