【问题标题】:How to bypass UsernamePasswordAuthentication in Spring Security如何在 Spring Security 中绕过 UsernamePasswordAuthentication
【发布时间】:2017-09-05 01:25:12
【问题描述】:

我正在实现一个接受 JWT 作为请求参数并在身份验证时返回新 JWT 的 API。

@RequestMapping(value = "/authenticate/token", method = RequestMethod.POST,
    consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity authenticate(@RequestParam("login_token") final String token, HttpServletResponse response) {
    LOG.debug("Request to login with token : {}", token);
    try {
        String jwt = authService.loginByToken(token);
        response.addHeader(JWTConfigurer.AUTHORIZATION_HEADER, "Bearer " + jwt);
        return ResponseEntity.ok(new IdentityToken(jwt));
    } catch (AuthenticationException ae) {
        LOG.trace("Authentication exception trace: {}", ae);
        return new ResponseEntity<>(Collections.singletonMap("AuthenticationException",
            ae.getLocalizedMessage()), HttpStatus.UNAUTHORIZED);
    }
}

我的 loginByToken 实现如下所示

@Override public String loginByToken(String token) {
    if (!tokenProvider.validateToken(token)) {
        throw new BadCredentialsException("Token is invalid.");
    }
    SecureToken secureToken = tokenProvider.parseJwtToken(token);
    User user = userRepository.findByEmail(secureToken.getEmail());

    // TODO: Check Account Status is valid, User status is valid

    Calendar c = Calendar.getInstance();
    c.setTime(new Date());
    c.add(Calendar.DATE, Constants.PASSWORD_EXPIRY_DAYS);

    if (user.getPasswordExpiryDt() != null
        && user.getPasswordExpiryDt().after(c.getTime())) {
        throw new BadCredentialsException("Password changed");
    }

    // TODO: Find how to create authentication object and return ID token.
    // return tokenProvider.createToken(authentication, false);
    return token;
}

此时,我不确定如何创建一个身份验证对象,该对象包含我可以传递给创建身份令牌的createToken 函数的所有用户详细信息。

这是我的项目,没有本文中提到的更改 - https://github.com/santoshkt/ngx-pipes-test

我已阅读有关匿名身份验证、预身份验证等信息,但不知道如何处理这种情况。将不胜感激有关如何执行此操作的任何指示。

【问题讨论】:

    标签: spring authentication spring-boot spring-security jwt


    【解决方案1】:

    如果您想使用 Spring Security,您可能不应该使用 Spring MVC 端点来处理(预)身份验证。

    在您的情况下,您可能希望更改 Spring 安全配置,以便它具有从请求参数中获取令牌的过滤器和从令牌中检索用户/身份验证对象的身份验证提供程序:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/authenticate/token")
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            // This is a filter bean you'll have to write
            .addFilterBefore(filter(), RequestHeaderAuthenticationFilter.class)
            // This is your token verifier/decoder
            .authenticationProvider(authenticationProvider())
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        }
    

    对于过滤器,您可以从AbstractPreAuthenticatedProcessingFilter 扩展并使其返回login_token 参数。在这里你必须实现两个方法是getPreAuthenticatedPrincipal()getPreAuthenticatedCredentials()

    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        // You could already decode your token here to return your username
        return request.getParameter("login_token");
    }
    
    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        return request.getParameter("login_token");
    }
    

    您的身份验证提供程序的类型应为PreAuthenticatedAuthenticationProvider,您可以在此处设置AuthenticationUserDetailsService

    @Bean
    public AuthenticationProvider authenticationProvider() {
        PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
        // service is a bean of type AuthenticationUserDetailsService
        // You could autowire this in your security configuration class
        provider.setPreAuthenticatedUserDetailsService(service);
        return provider;
    }
    

    现在您可以创建自己的AuthenticationUserDetailsService 以根据您的令牌检索UserDetails 对象:

    @Service
    public class TokenAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
    
        @Override
        public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken authentication) throws UsernameNotFoundException {
            // In this case the authentication.getCredentials() will contain your token and you can return a UserDetails object
           return new User(/** ... */);
        }
    }
    

    【讨论】:

      【解决方案2】:

      由于您想为 JWT 令牌请求提供 HTML 页面,因此最好的方法是创建您自己的 Spring Security Custom Entry Point 你可以看看here的例子

      如果是另一个系统来管理身份验证,而您只想管理授权,则可以“信任”另一个系统,然后管理自己的授权;在这种情况下,您可以使用PreAuthentication Scenario,如here 所述;你可以找到一个样本here

      希望有用

      【讨论】:

        猜你喜欢
        • 2013-10-13
        • 2021-08-15
        • 2013-09-20
        • 2016-06-24
        • 2013-04-13
        • 2011-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多