【问题标题】:Spring boot basic authentication with token for a RESTAPI带有 REST API 令牌的 Spring Boot 基本身份验证
【发布时间】:2019-04-03 20:03:54
【问题描述】:

我需要为 SpringBoot 应用程序提供用户登录。

用户登录请求将是一个 Rest 请求,其有效负载由“用户名”和“密码”组成。

我需要第一次从数据库验证这些凭据并生成一个在特定时间有效的令牌。 然后登录后所有后续请求都会有该令牌,并且每次都会验证该令牌。

我已经完成了令牌验证部分,但我对第一次登录感到很困惑,我不知道该怎么做。

即使是第一次登录请求,系统也会检查明显失败的令牌身份验证。

我希望系统在从数据库验证名称和密码后第一次简单地生成令牌。

这是我第一次使用 Spring Boot Security 实现用户登录,所以我对此一无所知。虽然我在网上研究和阅读了很多,但仍然无法弄清楚这部分。

  • 编辑:

以下是扩展 WebSecurityConfigurerAdapter 的安全配置类

        @Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

     auth.userDetailsService(userDetailsService)
    .passwordEncoder(getPasswordEncoder());
}



@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable();
    http.authorizeRequests()
    .antMatchers("/","**/firstPage").authenticated()
            .anyRequest().permitAll()
            .and()
            .formLogin().loginPage("/login").
            permitAll()
            .and().logout().permitAll();
}

以下是登录后将调用的请求。如何使用已经生成的令牌对其中的用户进行身份验证? Token 正在请求的 Header 中发送。

 @PostMapping(value = "/home")
public ResponseEntity<ConsolidateResponse> TestReques(@RequestBody TestParam testParam)
        throws Exception {

    //Some logic

   }

【问题讨论】:

  • 基本上,对于登录端点,您应该允许没有身份验证的请求。这可以在扩展 WebSecurityConfigurerAdapter 的网络安全配置类中完成
  • 如果你可以添加你的网络安全配置类(扩展WebSecurityConfigurerAdapter的那个),我可以告诉你如何做到这一点。
  • @MadhuBhat 禁用默认身份验证后,应用程序将如何验证登录请求后的所有请求?以及如何处理令牌过期?
  • 身份验证只会在登录端点上禁用,而不会在其余端点上禁用。如果你能展示你已经尝试过的代码,我可以帮你。
  • @MadhuBhat 我已经更新了我的问题。现在您将有一个更清晰的画面。请告诉我如何验证后续请求。

标签: spring spring-boot authentication access-token


【解决方案1】:

如果您从 Spring 安全配置类禁用表单登录并公开一个休息端点 (/auth),您可以处理登录并生成令牌。这里我使用 jwt 生成令牌。

 @RequestMapping(value = "/auth", method = RequestMethod.POST)
    public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest) throws AuthenticationException, IOException {
        // Perform the security
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                authenticationRequest.getUsername(), authenticationRequest.getPassword());

        final Authentication authentication = authManager.authenticate(token);
        if (!authentication.isAuthenticated()) {
            throw new BadCredentialsException("Unknown username or password");
        }

        // Reload password post-security so we can generate token
        final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
        final String jwtoken = jwtTokenUtil.generateToken(userDetails);
        return ResponseEntity.ok(responseBean);
    }

当使用无状态身份验证时,我们可以将令牌参数显式传递给控制器​​并对其进行验证。如果基于会话的身份验证开启,我们还可以使用@AuthenticationPrincipal 来检索当前登录的用户。

//Stateless authentication
@PostMapping(value = "/home")
public ResponseEntity<ConsolidateResponse> test(@RequestBody TestParam testParam,String token)
        throws Exception {


    Boolean isValidToken = jwtTokenUtil.validateToken(token);
    if(isValidToken) {
     //Some logic 
    }else {
     //invalid request
    }
}





@PostMapping(value = "/home")
    public ResponseEntity<ConsolidateResponse> test(@RequestBody TestBean requestToken,
            @AuthenticationPrincipal User contextPrincipal, HttpServletRequest req) {

        Optional.ofNullable(contextPrincipal).orElseThrow(InvalidUserSession::new);


        //some logic
    }

【讨论】:

  • 此方法是否会处理后续请求和令牌到期的身份验证?
  • @Just_another_developer 此方法用于登录和生成令牌。要检查令牌是否已过期或此用户已登录用户,您只需将令牌参数添加到“/home”端点并验证令牌。我会快速更新我的答案
  • 感谢您的帮助,不过我有点困惑,如果有人拥有此令牌,即使不登录也可以访问该应用程序,这是真的吗?假设我创建了一个有效期为一天的令牌,一些黑客拦截了请求并获取了令牌,现在他们甚至可以在没有真正获得身份验证的情况下访问应用程序。对吧?
  • 是的,如果有人拥有有效的令牌,那么他就可以访问资源。您可以使用 https 来保护流量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 2018-06-21
  • 2018-11-24
  • 2016-07-16
  • 2020-08-21
  • 2015-01-11
  • 1970-01-01
相关资源
最近更新 更多