当前位置: 首页 > 知识库问答 >
问题:

Spring Security:在运行时注册用户

翁良弼
2023-03-14

我有一个具有两个endpoint的服务:

  1. 公共endpoint:任何人都可以访问它,并打开用户帐户(注册)
  2. 受保护endpoint:只有注册用户才能访问它,将授权头用作HTTP POST请求的一部分

用例:

  • 用户首先到达公共endpoint并通过HTTP POST打开帐户,该JSON包含userName。然后服务生成密码,并将其作为JSON响应传递回用户。
  • 用户从服务中拿回密码后,他应该使用这个密码(连同他的userName)通过在Authoration Header中传递他的凭据来访问受保护的endpoint

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

我面临的问题是,当第一个用户在公共endpoint上注册时,在那一刻之后,访问受保护的endpoint不再需要更多的授权!每个凭据都可以工作,甚至没有授权标头的请求也可以工作。我不知道为什么我会有这种不良行为,所以任何关于如何纠正这种行为的建议都会很好!

打开用户帐户的公共endpoint

@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);
}

用户服务.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);
        }
    }

用户详细信息服务.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());
}

受保护(授权)endpoint

@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();
    }
}

同样,想要的行为是:

    < li >在" localhost:8080/user "上创建新的用户帐户 < li >然后点击“localhost:8080/hello ”,这要求上面注册的任何用户进行身份验证,否则以未经授权的响应进行响应

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

共有1个答案

靳富
2023-03-14

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

  /**
   * 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();
  }
 类似资料:
  • 我正在搜索一个在运行时注册@RestController的解决方案。我目前正在向

  • 只需要社区评估的东西。下面是一段代码,这是一个创建特定类型实例的简单工厂。该方法将在上下文中注册bean作为原型并返回实例。这是我第一次在运行时配置bean。你能好心评估并提供反馈吗?事先谢谢你。 FLEX Sync工厂已在IoC容器中配置为单例。因此,要创建一个新的同步管理器,我需要执行以下操作: 我使用的是Spring 3.1。请回顾并提供宝贵的反馈。 亲切的问候。

  • 问题内容: 只需要一些由社区评估的东西。以下是一段代码,这是一个创建特定类型实例的简单工厂。该方法将在上下文中将bean注册为原型并返回实例。这是我第一次在运行时配置bean。您能否评价并提供反馈?先感谢您。 FLEX Sync工厂已在IoC容器中配置为单例。因此,要创建新的同步管理器,请执行以下操作: 我正在使用Spring 3.1。请查看并提供您宝贵的反馈意见。 亲切的问候。 问题答案: 这纯

  • 我有一个叫做srxCOM的dll。用于titan FTP的dll,此dll是为VB6制作的。我想在Visual Studio中使用dll。NET,所以我使用tblimp创建了一个运行时可调用的包装器,并将其命名为srxCOMnet。dll。我在VS项目中添加了dll作为参考,可以访问其中的函数。在创建项目时,我遇到了这个错误, 错误:CLSID{A82C6CF0-7B42-4ABD-AECB-98

  • 我试图在运行时动态创建POJO类并将它们映射到Hibernate。但是,我在第二部分失败了。 生成类文件后,我将其放置在Hibernate扫描POJO的位置。但它不起作用。 我再次尝试重建会话工厂,以便它可以接收新创建的文件,但这不起作用。重建会话工厂也不是一个好的/可扩展的解决方案。 Hibernate设置代码: 错误:

  • 问题内容: 通过Maven插件运行时,我试图使VertX Mertrics正常工作exec:java。 当我将应用程序打包到fatjar中并使用以下命令运行时,所有工作均按预期进行 当我运行它时,我看到: 我尝试了几种方法: 添加为编译依赖项 创建内部指标实施并通过文件进行注册(请仔细检查其是否已实际复制到 还添加为附加的classpath元素(除了上一点之外) 我已经仔细检查了ServiceLo