【问题标题】:Spring Boot Data Rest JPA - Entity custom create (User)Spring Boot Data Rest JPA - 实体自定义创建(用户)
【发布时间】:2015-10-03 02:56:10
【问题描述】:

我正在尝试学习 Spring。我使用以下工具使用 Spring Boot 创建了一个项目:

  • Spring 数据 JPA
  • Spring 数据 REST
  • 春天的仇恨
  • Spring 安全性

我正在尝试创建一个User 实体。我希望用户有一个加密的密码(+ salt)。

当我执行POST 到/api/users 时,我成功创建了一个新用户。

{
"firstname":"John",
"lastname":"Doe",
"email":"johndoe@example.com",
"password":"12345678"
}

但我有两个问题:

  • 密码以明文形式保存
  • 盐为空
+----+---------------------+-----------+----------+----------+------+
| id |        email        | firstname | lastname | password | salt |
+----+---------------------+-----------+----------+----------+------+
|  1 | johndoe@example.com | John      | Doe      | 12345678 | NULL |
+----+---------------------+-----------+----------+----------+------+

我认为的问题是使用了默认构造函数,而不是我创建的另一个构造函数。我是 Spring 和 JPA 的新手,所以我一定遗漏了一些东西。这是我的代码。

User.java

@Entity
@Table(name = "users")
public class User{

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    public String firstname;

    @Column(nullable = false)
    public String lastname;

    @Column(nullable = false, unique = true)
    public String email;

    @JsonIgnore
    @Column(nullable = false)
    public String password;

    @JsonIgnore
    @Column
    private String salt;

    public User() {}

    public User(String email, String firstname, String lastname, String password) {
        this.email = email;
        this.firstname = firstname;
        this.lastname = lastname;
        this.salt = UUID.randomUUID().toString();
        this.password = new BCryptPasswordEncoder().encode(password + this.salt);
    }


    @JsonIgnore
    public String getSalt() {
        return salt;
    }

    @JsonProperty
    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getEmail() {
        return email;
    }

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

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    @JsonIgnore
    public String getPassword() {
        return password;
    }

    @JsonProperty
    public void setPassword(String password) {
        this.password = password;
    }

}

UserRepository.java

public interface UserRepository extends JpaRepository<User, Long> {

    public User findByEmail(String email);

    public User findByEmailAndPassword(String email, String password);
}

Application.java

@SpringBootApplication
public class Application {


    public static void main(String[] args) {
        SpringApplication.run(Application .class, args);
    }

}

另外,如果有人发现我做错了什么,我想指出我应该在哪里/如何放置用户登录代码(解密)。

谢谢。

【问题讨论】:

  • 你的 REST @RestController 在哪里?
  • @Makoton 我没有。 Spring Data Rest 自动在 RESTful API 中公开我的实体。在这种情况下我需要一个吗?
  • 你是否尝试创建一个 UserService 和: public void registerUser(final User user) { final String encodedPassword = passwordEncoder.encode(user.getPassword()); user.setPassword(encodedPassword); userRepo.save(用户); }
  • @Makoton 不,我没有。我会这样做并回帖。谢谢!
  • @agnostos 你的问题解决了吗?如果没有,您是否尝试过我的答案中的解决方案?

标签: spring jpa spring-boot spring-data spring-data-jpa


【解决方案1】:

所以,这就是我解决问题的方法:我创建了一个控制器作为我的自定义端点,然后我创建了一个服务,我在其中放置了创建用户所需的逻辑。代码如下:

UserController.java

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/api/register")
    @ResponseBody
    public Long register(@RequestBody User user) {
        return userService.registerUser(user);
    }

    ...

}

用户服务.java

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public Long registerUser(User user) {
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        userRepository.save(user);
        return user.getId();
    }

        ...

}

所以通过POST 与

{
"firstname":"John",
"lastname":"Doe",
"email":"johndoe@example.com",
"password":"12345678"
}

在/api/register 中,我现在可以使用散列密码创建用户。

【讨论】:

    【解决方案2】:

    如果你想让 Spring 使用你的构造函数,你需要

    • 删除无参数构造函数
    • 像这样用@JsonProperty注释另一个构造函数中的每个参数
    public User(@JsonProperty("email") String email, 
                @JsonProperty("firstname") String firstname, 
                @JsonProperty("lastname") String lastname, 
                @JsonProperty("password") String password) {
        this.email = email;
        this.firstname = firstname;
        this.lastname = lastname;
        this.password = new BCryptPasswordEncoder().encode(password);
    }
    

    您无需为BCryptPasswordEncoder 提供盐值,因为它已经自行对密码进行了盐化。

    【讨论】:

    • 当其中一个参数是对另一个实体的引用时,你会怎么做?那可以使用@JsonProperty 吗?
    猜你喜欢
    • 2015-03-25
    • 2019-09-30
    • 2017-08-15
    • 2019-10-01
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    相关资源
    最近更新 更多