10

MVCSpringアプリで Spring Security を使用しています。

JdbcUserDetailsManager認証のために次のクエリで初期化されます。

select username, password, enabled from user where username = ?

そして、当局はここにロードされています:

select u.username, a.authority from user u join authority a on u.userId = a.userId where username = ?

ユーザー名とメールの両方でログインできるようにしたいと思います。それを達成するためにこれら2つのクエリを変更する方法はありますか? それとももっと良い解決策がありますか?

4

7 に答える 7

5

残念ながら、クエリを変更するだけでこれを行う簡単な方法はありません。問題は、Spring Security が users-by-username-query と authority-by-username-query に単一のパラメーター (ユーザー名) があることを期待しているため、クエリに次のような 2 つのパラメーターが含まれている場合

username = ? or email = ?

クエリは失敗します。

あなたができることは、クエリ(またはクエリ)を実行してユーザー名または電子メールでユーザーを検索する 独自のUserDetailsS​​erviceを実装し、この実装をSpringセキュリティ構成の認証プロバイダーとして使用することです

  <authentication-manager>
    <authentication-provider user-service-ref='myUserDetailsService'/>
  </authentication-manager>

  <beans:bean id="myUserDetailsService" class="xxx.yyy.UserDetailsServiceImpl">
  </beans:bean>
于 2013-01-02T15:12:48.287 に答える
5

私は同じ問題を抱えていました.プロシージャを使用して、さまざまなクエリを試した後...これが機能することがわかりました:

public void configAuthentication(AuthenticationManagerBuilder auth)
        throws Exception {
    // Codificación del hash
    PasswordEncoder pe = new BCryptPasswordEncoder();

    String userByMailQuery = "SELECT mail, password, enabled FROM user_ WHERE mail = ?;";
    String userByUsernameQuery = "SELECT mail, password, enabled FROM user_ WHERE username=?";
    String roleByMailQuery = "SELECT mail, authority FROM role WHERE mail =?;";

    auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe)
            .usersByUsernameQuery(userByMailQuery)
            .authoritiesByUsernameQuery(roleByMailQuery);

    auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe)
            .usersByUsernameQuery(userByUsernameQuery)
            .authoritiesByUsernameQuery(roleByMailQuery);

}

2 つのクエリで構成を繰り返すだけです。

于 2015-10-07T08:46:09.837 に答える
2

これを正しく理解していれば、問題は、ユーザーが2つの異なるDB列に入力したユーザー名を検索することです。

もちろん、UserDetailsS​​erviceをカスタマイズすることでそれを行うことができます。

public class CustomJdbcDaoImpl extends JdbcDaoImpl {

    @Override
    protected List<GrantedAuthority> loadUserAuthorities(String username) {
    return getJdbcTemplate().query(getAuthoritiesByUsernameQuery(), new String[] {username, username}, new RowMapper<GrantedAuthority>() {
            public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
              .......
            }
        });
    }

    @Override
    protected List<UserDetails> loadUsersByUsername(String username) {
        return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] {username, username}, new RowMapper<UserDetails>() {
            public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                 .......
            }
        });
}

このクラスのBean構成は次のようになります。

<beans:bean id="customUserDetailsService" class="com.xxx.CustomJdbcDaoImpl">
    <beans:property name="dataSource" ref="dataSource"/>
    <beans:property name="usersByUsernameQuery">
        <beans:value> YOUR_QUERY_HERE</beans:value>
    </beans:property>
    <beans:property name="authoritiesByUsernameQuery">
        <beans:value> YOUR_QUERY_HERE</beans:value>
    </beans:property>
</beans:bean>

クエリは次のようになります

select username, password, enabled from user where (username = ? or email = ?)
select u.username, a.authority from user u join authority a on u.userId = a.userId where (username = ? or email = ?)
于 2013-01-02T15:24:09.320 に答える
2

以下のコードのように UserDetailesService.and config を使用できます。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

ポイントは、同じユーザー名でユーザーを返す必要はなく、ユーザーのメールを取得してユーザー名でユーザーを返すことができるということです。コードは以下のコードのようになります。

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String usernameOrEmail) throws UsernameNotFoundException {
        var user = /** here search user via jpa or jdbc by username or email **/;
        if(user == null ) 
            throw new UsernameNotFoundExeption();
        else return new UserDetail(user); // You can implement your user from UserDerail interface or create one;
    }

}

ヒント * UserDetail はインターフェースであり、作成するか、Spring Default を使用できます。

于 2020-04-09T13:21:53.650 に答える
1

<jdbc-user-service>タグ内users-by-username-queryおよびauthorities-by-username-query属性でそれぞれカスタム クエリを定義できます。

<jdbc-user-service data-source-ref="" users-by-username-query="" authorities-by-username-query=""/>

アップデート

org.springframework.security.core.userdetails.UserDetailsServiceアプリケーションを認証ソースとして使用するように実装および構成するクラスを作成できます。カスタム UserDetails サービス内で、データベースからユーザーを取得するために必要なクエリを実行できます。

于 2013-01-02T13:56:40.030 に答える