mysql - Spring 安全: Getting MySQL duplicate entry error when registering more than one user

标签 mysql spring jdbc spring-security spring-data-jpa

我正在尝试使用 Spring Security 注册和登录用户,并为他们提供角色,这是 Spring Security 所需的。目前,我在注册多个用户时收到以下错误。

错误是:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:键“UK_8sewwnpamngi6b1dwaa88askk”的重复条目“USER”

对于许多用户来说,role_name 可以是相同的,因此我为角色创建了一个“id”,它是主键,并且是自动生成的。我的 MySQL 数据库中的“USER_ROLES”表只有一个条目,即第一封电子邮件,以及角色名称“USER”。 Customer 表包含所有条目,无论是否有错误。我会继续努力。

感谢您的浏览。

Customer.java

package com.example.demo.models;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

@Entity
public class Customer implements Serializable {

    @NotNull
    @Size(min=2, max=25)
    private String name;

    @GeneratedValue
    @Id
    private int accountNumber;

    private BigDecimal accountFunds;

    @NotNull
    @Size(min=2)
    private String password;

    @NotNull
    @Size(min=2, max=25)
    @Email
    private String email;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "USER_ROLES", joinColumns = {
            @JoinColumn(name = "CUSTOMER_EMAIL", referencedColumnName = "email")
    }, inverseJoinColumns = {
            @JoinColumn(name = "ROLE_NAME", referencedColumnName = "name")
    })
    private List<Role> roles;

    public Customer(String name, String password, String email) {
        this.name = name;
        this.password = password;
        this.email = email;
    }

    public Customer() {}

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAccountNumber() {
        return accountNumber;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public BigDecimal getAccountFunds() {
        return accountFunds;
    }

    public void setAccountFunds(BigDecimal accountFunds) {
        this.accountFunds = accountFunds;
    }

}

角色.java

package com.example.demo.models;


import javax.persistence.*;
import java.util.List;

@Entity
public class Role {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @ManyToMany(mappedBy = "roles")
    private List<Customer> customers;


    public Role(String name, List<Customer> customers) {
        this.name = name;
        this.customers = customers;
    }

    public Role(String name) {
        this.name = name;
    }

    public Role() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Customer> getCustomers() {
        return customers;
    }

    public void setCustomers(List<Customer> customers) {
        this.customers = customers;
    }
}

UserService.java

package com.example.demo.models.services;

import com.example.demo.models.Customer;
import com.example.demo.models.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserService {

@Autowired
private UserRepository userRepository;

public void createUser(Customer customer) {

    Role userRole = new Role("USER");
    List<Role> roles = new ArrayList<>();
    BCryptPasswordEncoder  encoder = new BCryptPasswordEncoder();
    customer.setPassword(encoder.encode(customer.getPassword()));
    roles.add(userRole);
    customer.setRoles(roles);

    userRepository.save(customer);
    }

    public void createAdmin(Customer customer) {

    Role userRole = new Role("ADMIN");
    List<Role> roles = new ArrayList<>();
    BCryptPasswordEncoder  encoder = new BCryptPasswordEncoder();
    customer.setPassword(encoder.encode(customer.getPassword()));
    roles.add(userRole);
    customer.setRoles(roles);

    userRepository.save(customer);

    }
}

用户存储库

package com.example.demo.models.services;

import com.example.demo.models.Customer;
import org.springframework.data.jpa.repository.JpaRepository;


public interface UserRepository extends JpaRepository<Customer, String> {
}

安全配置

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select email as principal, password as credentials, true from customer where email=?")
                .authoritiesByUsernameQuery("select customer_email as principal, role_name as role from user_roles where customer_email=?")
                .passwordEncoder(passwordEncoder()).rolePrefix("ROLE_");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers(
                        "/**/webjars/**",
                        "/cheese/signup",
                        "/cheese/login",
                        "/cheese/success").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/cheese/login")
                .defaultSuccessUrl("/cheese/account")
                .permitAll();
    }

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

最佳答案

好的,我已经开始工作了。 SecurityConfig 是相同的,只是您需要将 'role_name' 更改为 'role_id'。

为了给出一点解释,我做了以下操作:

  1. 将 ID 添加到角色,使其成为主键/自动生成。
  2. 对于客户多对多,我将客户电子邮件连接到(反向连接)角色“id”
  3. 对于角色,我做了一对多映射。将角色“id”与(反向连接)客户电子邮件连接起来。
这样,我最终得到了一个“user_roles”表,其中 role_id 映射到客户电子邮件,以及一个“role”表,其中 role_id 映射到角色(即“USER”、“ADMIN”等)。 ),允许重复。我仍然是一个初学者,所以也许这不是最好的方法,但它对我有用。

代码...

Customer.java

package com.example.demo.models;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

@Entity
public class Customer implements Serializable {

    @NotNull
    @Size(min = 2, max = 25)
    private String name;

    @GeneratedValue
    @Id
    private int accountNumber;

    private BigDecimal accountFunds;

    @NotNull
    @Size(min = 2)
    private String password;

    @NotNull
    @Size(min = 2, max = 25)
    @Email
    private String email;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_roles",
            joinColumns={@JoinColumn(name="CUSTOMER_EMAIL", referencedColumnName = "email")},
            inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="id")})
    private List<Role> roles;

    public Customer(String name, String password, String email) {
        this.name = name;
        this.password = password;
        this.email = email;
    }

    public Customer() {}

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAccountNumber() {
        return accountNumber;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public BigDecimal getAccountFunds() {
        return accountFunds;
    }

    public void setAccountFunds(BigDecimal accountFunds) {
        this.accountFunds = accountFunds;
    }
}

角色.java

package com.example.demo.models;


import javax.persistence.*;
import java.util.List;

@Entity
public class Role {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_roles",
            joinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="id")},
            inverseJoinColumns={@JoinColumn(name = "CUSTOMER_EMAIL", referencedColumnName = "email")
    })
    private List<Customer> customers;


    public Role(String name, List<Customer> customers) {
        this.name = name;
        this.customers = customers;
    }

    public Role(String name) {
        this.name = name;
    }

    public Role() {}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Customer> getCustomers() {
        return customers;
    }

    public void setCustomers(List<Customer> customers) {
        this.customers = customers;
    }
}

关于mysql - Spring 安全: Getting MySQL duplicate entry error when registering more than one user,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50533314/

相关文章:

如果条目是数字,PHP 仅删除行

mysql - 如何在vb.net WPF和MySQL中使用DataGrid获取/过滤两个日期之间的数据?

java - Spring MVC "No converter found capable of converting from type java.lang.String to type org.springframework.core.io.Resource"

java - 无法捕获 Spring 中异步方法抛出的异常

java - Glassfish MySQL Hibernate 无法构建 Hibernate SessionFactory

php - 如何在一个字段中选择两个字段

php mysql用户名变量包含两个值

java - 尝试部署到 AZURE 时出错无法执行目标 org.apache.maven.plugins :maven-surefire-plugin:2. 22.2:test

java - 使用 JDBC 更新数据库,其中包含一些应忽略的值

java - 从 ComboBox 中进行选择时,用数据库条目填充 JList