Spring安全性:在运行时注册用户

时间:2017-10-29 15:25:43

标签: java spring security authentication spring-security

我有一个有两个终点的服务:

  1. 公共端点:任何人都可以访问它,并打开用户帐户(注册)
  2. 受保护的端点:只有注册用户可以使用授权标头作为HTTP POST请求的一部分来访问它
  3. 用例:

    • 用户首先点击公共端点,然后通过HTTP POST打开包含userName的JSON的帐户。然后,该服务生成密码,并将其作为JSON响应传递回用户。
    • 用户从服务中取回密码后,他应使用此password(以及他的userName)通过传递其凭据来访问受保护的端点授权标题

    现在,显然,需要在运行时注册新用户

    我面临的问题是,当第一个用户在公共端点上注册时,在此之后,访问受保护的端点不再需要更多的授权!每个凭据都可以使用,甚至没有授权标题的请求也可以使用。我不知道为什么我会遇到这种不良行为,所以任何关于如何修复它的建议都会很棒!

    打开用户帐户的公共端点

    @RequestMapping(method = RequestMethod.POST, value = "/user", produces = "application/json")
    public ResponseEntity<UserCreatedResponse> create(@RequestBody String userName) {
            // generate user password
            String password = service.generatePassword();
    
            // save the user to the local repository
            service.save(userName, password);
    
            // use SecurityService to add a new user token --> something fishy here!
            security.login(userName, password);
    
    
            // returns response with a new user password
            return new ResponseEntity<UserCreatedResponse>(
                    new UserCreatedResponse(password),
                    HttpStatus.CREATED);
    }
    

    UserService.java 用于将用户保存到存储库

    public void save(String userName, String password) {
        repository.save(new User(userName, passwordEncoder.encode(password)));
    }
    
    用于存储登录凭据的

    SecurityService.java :我不确定这是否正确

    public void login(String userName, String password) {
            // usrDetailsService is the instance of UserDetailsService.java
            UserDetails usrDetails = usrDetailsService.loadUserByUsername(userName);
    
            UsernamePasswordAuthenticationToken token = 
                    new UsernamePasswordAuthenticationToken(usrDetails, password, usrDetails.getAuthorities());
    
            // authenticate token with the given account details
            authManager.authenticate(token);
    
            if (token.isAuthenticated()) {
                // provide authentication info to the context
                SecurityContextHolder.getContext().setAuthentication(token);
            }
        }
    

    UserDetailsS​​ervice.java

    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        // this is my custom User class
        User user = repository.findById(userName);
    
        // and this is org.springframework.security.core.userdetails.User
        return new User(user.getUsername(), user.getPasswordHash(), Collections.emptySet());
    }
    

    受保护(授权)端点

    @RequestMapping(method = RequestMethod.POST, value = "/hello", produces = "application/json")
    public String hello(@RequestBody MyRequest request) {
        return "Hello, authenticated!";
    }
    

    SecurityConfig.java

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http.authorizeRequests()
                                .antMatchers(HttpMethod.POST, "/user") 
                                .permitAll().anyRequest().authenticated();
    
            http.csrf().disable();
        }
    }
    

    同样,想要的行为是:

    • 在“localhost:8080 / user”
    • 上创建新用户帐户
    • 然后点击“localhost:8080 / hello”,这需要对上面注册的任何用户进行验证,否则以 Unathorized 响应进行响应

    缺少什么或我做错了什么?

1 个答案:

答案 0 :(得分:0)

您的安全配置是什么样的? 您可以指定应该打开哪些页面进行注册:

  /**
   * Configures the access rights for the application.
   *
   * @param http the HttpSecurity context of the application
   * @throws Exception some exception.
   */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        //Which URLs are available without any authentication
        .antMatchers("/about", "/help", "/imprint", "/register", "/registerExp", "/login**").permitAll()
        //Restrict access rights for any relative URL behind /admin/ to the ADMIN role
        .antMatchers("/admin/**").hasRole("ADMIN")
        //Any request needs to be fully authenticated (remember me does NOT suffice!)
        .anyRequest().fullyAuthenticated().and()
        //Specify the login process.
        .formLogin()
            .loginPage("/login")
            .failureHandler(authenticationHandler)
            .permitAll()
            .and().logout().permitAll()
            .and()
        .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).ignoringAntMatchers("/console/**");

    //Disables header security. This allows the use of the h2 console.
    http.headers().frameOptions().disable();
  }