用户在springboot中调用注册休息API时如何获取oAuth2访问令牌?

Posted

技术标签:

【中文标题】用户在springboot中调用注册休息API时如何获取oAuth2访问令牌?【英文标题】:How to get oAuth2 access token when user call signup rest API in springboot? 【发布时间】:2017-11-20 14:10:15 【问题描述】:

目前我正在研究 Springboot 安全性,这对我来说是全新的。我跟着youtube视频教程Video

当我使用下面的代码 sn-p 时,我成功获得了 oauth2 access_token:-

@SpringBootApplication
public class MathifyApplication 
    @Autowired
    private PasswordEncoder passwordEncoder;


    public static void main(String[] args) 
        SpringApplication.run(MathifyApplication.class, args);
    

    @Autowired
    public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository, UserService service) throws Exception 
        //Setup a default user if db is empty
        User students = new User("stu1", "user", "user", "abc@gmail.com", "1234567890", "12th", "dwarka sec-12", 
            0, 0 , "may/29/2017", "", Arrays.asList(new Role("USER"), new Role("ACTUATOR")));
        if (repository.count()==0)
            service.save(students);
        
        builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
    

    private UserDetailsService userDetailsService(final UserRepository repository) 
        return userName -> new CustomUserDetails(repository.findByUsername(userName));
    


而控制器类是:-

@RestController
public class LoginController 
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/mathify/getuser/userId", method = RequestMethod.GET)
    public User getUser(@PathVariable String userId)
        System.out.println("Userid "+userId);
        return userService.getUser(userId);
    

    @RequestMapping(method = RequestMethod.POST, value="/mathify/signup")
    public User register(@RequestBody User user)

        return userService.doSignup(user);

    

    @GetMapping(value="/hi")
    public String test()

         return "Oh ! I am fine without secuirity";
    


通过上面的代码sn-p,我可以得到access_token(/oauth/token),也可以毫无问题地调用其他控制器类私有API。

但是上面的代码有问题。什么?在上面的代码中,sn-p 用户是硬编码的,但是当我想在用户注册时获取 access_token 时,它给出了一个异常。

2017-06-18 11:04:05.689 ERROR 8492 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@6b66d7ac to already built object] with root cause

java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@6b66d7ac to already built object
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.add(AbstractConfiguredSecurityBuilder.java:196) ~[spring-security-config-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.apply(AbstractConfiguredSecurityBuilder.java:133) ~[spring-security-config-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.apply(AuthenticationManagerBuilder.java:290) ~[spring-security-config-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.userDetailsService(AuthenticationManagerBuilder.java:187) ~[spring-security-config-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at com.techiesandeep.mathify.controller.LoginController.register(LoginController.java:40) ~[classes/:na]

为了实现上述功能,我在应用程序和控制器中做了一些更改

应用程序类为:-

@SpringBootApplication
public class MathifyApplication 
    @Autowired
    private PasswordEncoder passwordEncoder;


    public static void main(String[] args) 
        SpringApplication.run(MathifyApplication.class, args);
    

Controller 类如下:-

@RestController
public class LoginController 
  @Autowired
        private UserService userService;
        @Autowired
        AuthenticationManagerBuilder builder;
        @Autowired
        private PasswordEncoder passwordEncoder;
        @Autowired
        private UserRepository repository;


        @RequestMapping(value = "/mathify/getuser/userId", method = RequestMethod.GET)
        public User getUser(@PathVariable String userId)
            System.out.println("Userid "+userId);
            return userService.getUser(userId);
        

        @RequestMapping(method = RequestMethod.POST, value="/user/signup")
        public User register(@RequestBody User user) throws Exception 
            User u = userService.doSignup(user);
            builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
            return u;
        

        private UserDetailsService userDetailsService(final UserRepository repository) 
            return userName -> new CustomUserDetails(repository.findByUsername(userName));
        

        @GetMapping(value="/hi")
        public String test()

             return "Oh ! I am fine without secuirity";
        

任何帮助将不胜感激。谢谢

【问题讨论】:

您正在动态构建身份验证管理器。这是我第一次看到这个,我强烈建议不要这样做。 @Shazin 基本上我想在成功注册其余 API 后给用户令牌,你能指导我吗?我为此在谷歌上搜索了很多,但没有得到任何相关的东西,任何链接或任何指导都会很有帮助,谢谢 您可以向 oauth/token 端点请求获取访问令牌。 【参考方案1】:

您可以调用另一个 POST 请求来获取访问令牌。 我不确定这是不是最好的方法,但对我来说效果很好。

注册请求映射中的示例代码片段:

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.set("Authorization", auth_header);
    /*auth_header should be Autorization header value that captured from signup request, which is generated by Basic Auth with clientID and secret, for example, "Basic bXktdHJ1c3RlZC1jbGllbnQ6c2VjcmV0" */
    HttpEntity<String> entity = new HttpEntity<String>("",headers);
    String authURL = "http://localhost:8080/oauth/token?grant_type=password&username=yourusername&password=yourpassword";
    ResponseEntity<String> response = restTemplate.postForEntity(authURL, entity, String.class);

    System.out.println(response.getBody());

【讨论】:

以上是关于用户在springboot中调用注册休息API时如何获取oAuth2访问令牌?的主要内容,如果未能解决你的问题,请参考以下文章

调用 REST API 时如何处理 Google Ads API 速率限制?

每次响应 401 Unauthorized 时在 DEV Env 中调用休息,PROD 工作正常

Spring Boot 休息 API

单元测试时如何处理 API 调用速率限制?

Spring Boot 休息忽略一类

使用 kubernetes 集群进行动态 rest api 调用的 Springboot 应用程序