如何在Spring Security中为电子邮件字段而不是用户名实现UsernamePasswordAuthenticationFilter

时间:2018-04-23 22:50:29

标签: spring spring-boot spring-security jwt servlet-filters

SpringSecurity本身有UsernamePasswordAuthenticationFilter,但我想使用电子邮件而不是用户名。 我曾经使用过这个类这样的用户名:

public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

    private AuthenticationManager authenticationManager;
    private JwtUserDetailsToUserDTOConverter jwtUserDetailsToUserDTOConverter = new JwtUserDetailsToUserDTOConverter();

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override 
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        try {
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);

            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override 
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {


        String token = JwtGenerator.builder().build().generate((JwtUserDetails) authResult.getPrincipal());



        response.addHeader(JwtConstants.HEADER,JwtConstants.PREFIX + token);
    }



}

我想为电子邮件和密码实施AuthenticationFilter。 SpringSecurity中没有任何指定的此类意图类。 如何为电子邮件自定义它?

1 个答案:

答案 0 :(得分:1)

  • UsernamePasswordAuthenticationFilter只是从请求中提取用户名(可以是电子邮件)和密码,然后将其转发到配置的AuthenticationManager
  • 默认值(假设您没有覆盖它),使用的AuthenticationManager的实现是ProviderManager
  • 依次使用ProviderManager配置AuthenticationProvider。在大多数情况下,这将是DaoAuthenticationProvider。
  • 从DaoAuthenticationProvider调用到达UserDetailsService#loadUserByUsername(),它会尝试根据给定的用户名从DB中查找用户。

所以你有几个选择:

  1. 创建一个自定义UserDetailsS​​ervice,并重写loadUserByUsername(),它将给定的用户名与用户的电子邮件相匹配。然后可以将其设置为AuthenticationManagerBuilder实例,如下所示:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception            
        {    
            auth.userDetailsService(myUserDetailsService);
        }
    }
    
  2. 自定义AuthenticationProvider,用于根据电子邮件验证用户。这对您的方案来说有点过分,会导致代码重复。但是如果你想这样做,请使用与#1相同的代码,但调用auth.authenticationProvider(myAuthProviderInstance);代替