bugfix> mysql > 投稿

Spring Securityにユーザーを登録およびログインし、Spring Securityに必要なロールを付与しようとしています。複数のユーザーを登録すると、現在次のエラーが表示されます。

エラーは次のとおりです。

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:キー「UK_8sewwnpamngi6b1dwaa88askk」のエントリ「USER」が重複しています

role_nameは多くのユーザーで同じにすることができるため、主キーであり自動生成されるロールの「id」を作成しました。 MySQLデータベースの「USER_ROLES」テーブルには、最初のメールである1つのエントリと、role_name「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;
    }
}

Role.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);
    }
}

UserRepository

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> {
}

SecurityConfig

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

回答 1 件
  • わかりましたので、私はそれが動作するようになりました。 SecurityConfigは同じです。ただし、「role_name」を「role_id」に変更する必要があります。

    少し説明するために、次のことを行いました。

    IDをロールに追加し、プライマリキー/自動生成にします。

    多対多のお客様の場合、お客様のメールに「id」ロールを追加しました(逆参加)

    役割については、1対多のマッピングを行いました。ロール「id」への(逆結合)顧客メールへの参加。

    このようにして、role_idが顧客の電子メールにマップされた「user_roles」テーブルと、role_idがロール(つまり、「USER」、「ADMIN」など)にマップされた「role」テーブルになりました。複製用。私はまだ初心者なので、これでさえ最善の方法ではないかもしれませんが、私にとってはうまくいきました。

    コード...

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

    Role.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;
        }
    }
    
    

あなたの答え