如何在不重启 Spring Boot 的情况下使用 Spring Security 添加新用户

Posted

技术标签:

【中文标题】如何在不重启 Spring Boot 的情况下使用 Spring Security 添加新用户【英文标题】:How to add a new User with Spring Security without restart spring boot 【发布时间】:2021-06-18 19:57:42 【问题描述】:

spring boot启动完成后,Spring Security的配置无法更新。如何在不重启spring boot的情况下添加新用户或更新用户密码或用户角色?因为页面被重定向到 /login?error 页面,当我使用新密码登录时。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    MemberMapper memberMapper;

    Logger logger = Logger.getLogger(this.getClass());

    @Override
    protected void configure(HttpSecurity http) throws Exception 

        http.csrf().disable();
        http.addFilterBefore(new loginFilter(), AnonymousAuthenticationFilter.class).
                authorizeRequests().antMatchers("/","/register/**","/log/**").permitAll();



        http.formLogin().loginPage("/log/toLogin") 
                        .loginProcessingUrl("/log/login") 
                        .usernameParameter("memacc")
                        .passwordParameter("mempwd")
                        .failureHandler(new AppsAuthenticationFailureHandler());;





        http.logout().logoutSuccessUrl("/");


    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 

        List<Members> allMembers = memberMapper.getAllMembers();

        for (Members members : allMembers)
            String[] roleList = members.getRoleList().split(",");
            auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser(members.getMemacc()).password(new BCryptPasswordEncoder().encode(members.getMempwd())).roles(roleList);
        

    

【问题讨论】:

是否有使用 inMemoryAuthentication() 的特定需求?还是可以使用其他类型的身份验证? InMemoryAuthentication 基本上用于提供一组静态用户(可能仅用于测试目的)。如果您需要提供动态用户创建支持,则需要提供适当的注册流程 不,只是想使用简单的方式来处理动态用户创建或更新用户详细信息 inMemoryAuthentication 适用于固定用户。我可以使用 UserDetailsS​​ervice 动态身份验证吗? 【参考方案1】:

当您进行登录过程时,spring boots 会将用户配置文件保存在内存中。 例如,如果您为已登录的用户添加新角色并将其保存在数据库中,则内存中的用户配置文件不会更改,这就是您必须更新此数据的原因。

你可以做到:

User user = userService.findById(idUser);
    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getRoles()));

使用此命令,您可以更新 spring-security 内存中的用户配置文件。

【讨论】:

谢谢。我用你提供的方法解决了新的登录问题,但是当用户更改密码然后登录时它无法处理问题。 我不明白你的问题。如果您更改了数据库中的密码并在 Spring-security 中更改了用户,则您的用户已经更新并记录了。你不必做任何其他事情 是的,这种情况是可以的,但是用户在第一次注销再登录时不会被spring security认证。【参考方案2】:

谢谢大家, 我找到了解决方案。

...

@EnableWebSecurity

公共类 SecurityConfig 扩展 WebSecurityConfigurerAdapter

@Autowired
MyUserDetailsService myUserDetailsService;

Logger logger = Logger.getLogger(this.getClass());

@Override
protected void configure(HttpSecurity http) throws Exception 
 
    http.csrf().disable();
    
    http.addFilterBefore(new loginFilter(), AnonymousAuthenticationFilter.class).
            authorizeRequests().antMatchers("/","/register/**","/log/**").permitAll();

    
    http.formLogin().loginPage("/log/toLogin")
                    .loginProcessingUrl("/log/login") 
                    .usernameParameter("memacc")
                    .passwordParameter("mempwd");
    http.logout().logoutSuccessUrl("/");

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.userDetailsService(myUserDetailsService);

...

使用类实现 UserDetailsS​​ervice 接口。当用户登录时验证该用户。

... @服务 公共类 MyUserDetailsS​​ervice 实现 UserDetailsS​​ervice

@Autowired
MemberMapper memberMapper;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 

    Members member = memberMapper.getOneMemberByMemacc(username);
    if(member == null)
        throw new UsernameNotFoundException(username + " not found");
    UserDetails userDetails = User.builder()
            .username(member.getMemacc())
            .password("noop" + member.getMempwd())
            .roles(member.getRoleList()).build();
    return userDetails;

...

【讨论】:

以上是关于如何在不重启 Spring Boot 的情况下使用 Spring Security 添加新用户的主要内容,如果未能解决你的问题,请参考以下文章

如何在不从 spring-boot-starter-web 继承的情况下在 Spring Boot 中获取 ObjectMapper 实例?

如何在不使用 Spring Boot 的情况下注入 Feign Client 并调用 REST Endpoint

如何在不依赖 MongoDB 的情况下启动 spring-boot 应用程序?

如何在不维护 jsessionid 的情况下在 Spring Boot 中保护 RESTful API

如何在不启动 HikariPool 关闭的情况下使用 Hikari 数据源运行 Spring Boot 应用程序

如何使用 Java Spring Boot 在不插入新值的情况下更新表中的现有值