spring boot settings create user and modify user summary

Posted by mwmobley on Fri, 29 Oct 2021 15:00:45 +0200

  1. home page
  2. special column
  3. springboot
  4. Article details
0

spring boot settings create user and modify user summary

Hao Zelong_ HZ Published 2 minutes ago

preface

The blogger took a long time to modify the settings and create users. This is also for the tutorial Decorator mode With a deeper understanding.

Requirement description

The createUser and updateUser fields are added to each entity, representing the user who created the current data and the user who updated the current data respectively.

Difficulty analysis:

1. Find the annotation to perform the corresponding operation when the data is created and updated
2. Get the current login user

Pit stepping process

1. Perform operations during update or creation

The first thing you can see in google query by keyword is @ PrePersist and @ PreUpdate

@PrePersist: this annotation is used on a method to make the method execute before the persistence operation
@PreUpdate: this annotation is used on a method to enable the method to execute before performing data update and save operations

2. Get the current login user

Description: obtain the current login user on the @ PrePersist and @ PreUpdate annotation methods and set createUser and updateUser.

First thought:
1. Directly call getCurrentLoginUser (get current login user) method of userService

@Override
  public Optional<User> getCurrentLoginUser() {
    logger.debug("Obtain the current login user name according to the authentication and obtain the user name");
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null) {
      logger.debug("according to username call userRepository Get user")
      Optional<User> user = this.userRepository.findByUsername(authentication.getName());
      return user;
    }

    logger.debug("The authenticated user does not exist in the database");
    return Optional.empty();
  }

Result: it falls into a dead circle

Other attempts:
Use @ Transient to set the userRepository used in the entity to the attribute that does not exist in the entity. As a result, there are more errors.

@CreateBy and @LastModifiedBy

@CreateBy: sets the user who creates the data
@LastModifiedBy: sets the user who recently modified the data
Note: @ CreateBy and @ LastModifiedBy are usually used with AuditorAware

Auditing

What is database Auditing?
It keeps a track of who created or changed an entity and when the change happened.
so: AuditorAware is an interface that spring has this function

The three are used together

1. The fields of the specified entity use @ CreateBy and @ LastModifiedBy:

  @ManyToOne
  @JsonView(CreateUserJsonView.class)
  @NotFound(action = NotFoundAction.IGNORE)
  @CreatedBy
  private User createUser;

  @ManyToOne
  @JsonView(UpdateUserJsonView.class)
  @NotFound(action = NotFoundAction.IGNORE)
  @LastModifiedBy
  private User updateUser;

2. Add @ EntityListeners(AuditingEntityListener.class) annotation ① on the entity (or directly instantiate the AuditorAware interface with the entity) ②

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class YourClass{
}

@EnableWebMvc
@Configuration
@EnableJpaAuditing
public class WebConfig implements WebMvcConfigurer {
@Bean
    public AuditorAware<User> auditorProvider() {
        return new SpringSecurityAuditorAware();
    }

    private static class SpringSecurityAuditorAware implements AuditorAware<User> {

        @Autowired
        UserService userService;

        @Override
        public Optional<User> getCurrentAuditor() {
            // Get current login user
        }
    }
}
@MappedSuperclass
public class BaseEntity implements AuditorAware<User> {
  @Override
  public Optional<User> getCurrentAuditor() {
    // Get current login user
  }
}

effect

ERROR: when calling userRepository, it will still loop.
Since we call the findByUsername method of UserRepository, it essentially calls the method of CurdRepository. So why does it get the user and think that the data is created or updated, and then cycle? Because this method is not written by ourselves, there are many unknowns.

solve

Start with UserDetails: write your own UserDetails

Originally, UserDetails has no user field
Add user s to solve problems

public class UserDetailImpl extends org.springframework.security.core.userdetails.User implements UserDetails {
  private User user;
  public UserDetailImpl(String username, String password, Collection<? extends GrantedAuthority> authorities, User user) {
    super(username, password, authorities);
    this.user = user;
  }

  public User getUser() {
    return user;
  }
}

@Override
  public Optional<User> getCurrentLoginUserFirst() {
    logger.debug("Obtain the current login user name according to the authentication and obtain the user name");
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null) {
      UserDetailImpl userDetail;
      if (authentication instanceof UsernamePasswordAuthenticationToken) {
        logger.debug("The first method is to obtain the current login user after logging in. It is recommended to pick out this situation and verify it again with the method");
        userDetail = (UserDetailImpl) authentication.getPrincipal();
      } else if (authentication instanceof UserDetailImpl) {
        logger.debug("The second login user exists and is modifying data or adding new data");
        userDetail = (UserDetailImpl) authentication;
      } else if (authentication instanceof AnonymousAuthenticationToken) {
        logger.debug("The third is to modify or add data without login, such as changing password with mobile phone verification code");
        return Optional.empty();
      } else {
        throw new RuntimeException("Incorrect get type");
      }
      return Optional.of(userDetail.getUser());
    }

    logger.debug("The authenticated user does not exist in the database");
    return Optional.empty();
  }

Explanation: its essence is to use Decorator mode , define your own UserDetails and add a snapshot of the currently logged in user.

Effect: it is equivalent to giving each login user a snapshot. Take a chestnut: if the current login user is Zhang San, Zhang San will take a picture of Zhang San after logging in. Then it is assumed that Zhang San has had a facelift in the next few days, but the photos taken when Zhang San logs in have not changed, and so is the idea here

summary

As for the implementation of this requirement, I mainly focused on how to get the current login user without calling the findByUsername of UserRepository. Finally, I enabled the decorator mode under the guidance of the teacher. This time, I also improved my programming idea, and thank the teacher for his guidance.

Reading 7 was published 2 minutes ago
Like collection
89 prestige
10 fans
Focus on the author
Submit comments
You know what?

Register login
89 prestige
10 fans
Focus on the author
Article catalog
follow
Billboard

Topics: Spring Boot