java - JPA + MySql + 实现加密密码

标签 java mysql jpa encryption

当我为网站建立登录时,我想以一种安全的方式将自动生成的密码存储在 MySQL 中,从而以某种方式对其进行加密。但我不确定如何将自动生成与加密密码结合起来。

我看了很多问题,但没有一个真正帮助我或回答我的问题,因为它应该是自动生成的。另外,如果可能的话,我想以一种优雅的方式解决它,而无需硬编码和其他东西。如果有人能帮助我,我会很高兴,因为我是初学者,在此先感谢!

问题:

我如何自动生成安全的加密密码,我应该在 Java 中使用什么数据类型(目前是字符串),然后它映射到什么数据库类型?

如何确保我可以解密数据库的密码以检查它是否在有人登录时匹配?

用户实体:

@Entity
public class User {

    @Id
    @GeneratedValue
    private Integer user_id;
    
    @Column(unique = true)
    private String username;
    
    private String password;
    
    @Enumerated(EnumType.STRING)
    private Role role;
    
    //non-Owning (address) side of the OneToOne relationship
    @OneToOne(mappedBy = "user")
    private RetailStore retailStore;

    /**
     * Constructor
     */
    protected User() {
        
    }
    
    /**
     * Constructor
     * @param username
     * @param role
     */
    public User(String username, String password, Role role) {
        super();
        this.username = username;
        this.password = password;
        this.role = role;
    }

用户存储库:

@Repository
@Transactional
//necessary to be in an transaction to change something in database, 
//instead of doing this for every method itself it is declared by 
//the annotation @Transactional
public interface UserRepository extends JpaRepository<User, Long>{
    
}

最佳答案

解决了它,对我来说它工作完美而且看起来很漂亮。

不幸的是,没有真正的简短答案,就我个人而言,我花了很多时间在互联网上,然后有点自己构建它,但也许它对某人有帮助:

  • 使用 Spring Security 结合 JWT --> 通过 Spring 使用 UserDetails,实现服务(只有 loadByUsername 是真正需要在此类中实现的,以便在登录时 spring security 在数据库中查找用户)和它的 dto 和设置正确的配置,告诉 Spring 你想使用 JWT,BCRYPT(见下面的配置类)
  • 使用 BCRYPT(仅调用方法和 Autowiring BCRYPT 的盐和散列)(参见 UserDetailsS​​ervice)
  • 将密码设置为字符串实例,每个 java 字符串默认映射到数据库 mySQL 中的 VARCHAR(255)

例如 JWT 的许多代码,您只需复制即可。但我将展示我的 UserDetailsS​​ervice,它更像是一个单独的东西,用于管理用户,也是配置的一部分,它告诉 spring 如何处理权限和授权,包括 JWT 等等。

配置

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AuthConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

  @Autowired
  private UserDetailsService jwtUserDetailsService;

  @Autowired
  private JwtRequestFilter jwtRequestFilter;

  @Value("${jwt.get.token.uri}")
  private String authenticationPath;

  /**
   * Configure AuthenticationManager so that it knows from where to load user for
   * matching credentials. Use BCryptPasswordEncoder.
   *
   * @param auth which creates authentication manager
   * @throws Exception if authentication manager has problems
   */
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
  }

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  /**
   * Configure who has access to which URLs. Organize authorities and their needed
   * Authorization.
   */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // no need of CSRF
    http.csrf().disable()
        // authenticate particular requests
        .authorizeRequests().antMatchers("/adm/*").hasAuthority("ADMIN")
        .antMatchers("/store/{username}/*").hasAuthority("STORE").and()
        // make sure we use stateless session; session won't be used to
        // store user's state.
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    // Add a filter to validate the tokens with every request
    http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
  }

  /**
   * Configure which URLs can be ignored by spring web security. Thus there is no
   * authentication.
   */
  @Override
  public void configure(WebSecurity webSecurity) throws Exception {
    // no authentification needed for specific URLs (login request,...)
    webSecurity.ignoring().antMatchers(HttpMethod.POST, authenticationPath)
        .antMatchers(HttpMethod.OPTIONS, "/**");
  }
}

UserDetailsS​​ervcie

@Service
public class JwtUserDetailsService implements UserDetailsService {

  @Autowired
  private UserRepository userrepo;

  @Autowired
  private RetailStoreRepository storerepo;

  @Autowired
  private PasswordEncoder bcryptEncoder;

  // Aggregated root

  public List<User> findAllUser() {
    return userrepo.findAll();
  }

  // Single Item

  /**
   * Add new user (ADMIN or STORE).
   *
   * @param account information about new user
   * @return new user
   */
  public AccountDto addUser(AccountDto account) {
    String username = account.getUser().getUsername();
    // encode password (hashing)
    String code = bcryptEncoder.encode(account.getUser().getPassword()).toString();
    Role role = account.getUser().getRole();
    // create new user
    User user = new User(username, code, role);
    // add new user to database
    userrepo.save(user);
    // check authorization and add store if needed
    if (account.getUser().getRole().equals(Role.STORE) && account.getStore() != null) {
      storerepo.save(account.getStore());
    }
    return account;
  }

  /**
   * Delete user.
   *
   * @param userId id of user who is deleted
   */
  public void deleteUser(Long userId) {
    // check if user exists
    if (userrepo.existsById(userId)) {
      userrepo.deleteById(userId);
      // also delete corresponding retail store if it is no admin
      User user = userrepo.findById(userId).get();
      if (user.getRole().equals(Role.STORE)) {
        RetailStore trashStore = storerepo.findByUser_userId(userId);
        storerepo.delete(trashStore);
      }

    } else {
      throw new UserNotFoundException(userId);
    }

  }

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userrepo.findByUsername(username);
    if (user == null) {
      throw new UsernameNotFoundException("User not found with username: " + username);
    }
    return new JwtUserDetailsDto(user.getUserId(), user.getUsername(), user.getPassword(),
        user.getRole().toString());
  }

}

关于java - JPA + MySql + 实现加密密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63217082/

相关文章:

java - @joincolumn 的 Hibernate 默认值

java - SonarQube - 可以通过存储外部可变对象来公开内部表示

java - NetBeans 程序链接

MySQL 存储过程无法产生结果

php - 错误,查询创建表失败

java - EclipseLinkJpaVendorAdapter 而不是 HibernateJpaVendorAdapter 问题

java - Java 中的构造函数是否有访问修饰符继承?

java - Page.render() 返回 false

mysql - 通过php连接xcode到mysql

java - 带有 Predicate 的 Spring Data JPA 方法 findAll() - QueryDslPredicateExecutor