{“登录”:“testuser”,“邮件”:“testuser@gmail.com”,“密码”:“123abc”}
现在的问题是:我听说我们不应该将密码存储为字符串,而是在Java中存储为char数组,所以我就是这么做的。
下面是我的用户类
package com.mailReminder.restservice.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import javax.persistence.*;
import java.util.Arrays;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String login;
private String mail;
private char[] password;
private byte[] salt;
public User(String login, String mail, char[] password) {
this.login = login;
this.mail = mail;
this.password = password;
}
public User() {
this.id = 0L;
this.login = "";
this.mail = "";
this.password = null;
this.salt = null;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = password;
}
public byte[] getSalt() {
return salt;
}
public void setSalt(byte[] salt) {
this.salt = salt;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", login='" + login + '\'' +
", mail='" + mail + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.mailReminder.restservice.security;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class PasswordSecurer{
public static byte[] getSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
return salt;
}
public static byte[] hashPassword(char[] password, byte[] salt) {
int iterationCount = 65536;
int keyLength = 640;
KeySpec spec = new PBEKeySpec(password, salt, iterationCount, keyLength);
SecretKeyFactory factory = null;
try {
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return factory.generateSecret(spec).getEncoded();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
}
package com.mailReminder.restservice.controller;
import com.mailReminder.restservice.model.User;
import com.mailReminder.restservice.repository.UserRepository;
import com.mailReminder.restservice.security.PasswordSecurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@RestController
public class UserController {
private final UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@PostMapping("/register")
public ResponseEntity<Object> register(@RequestBody User newUser) {
byte[] salt = PasswordSecurer.getSalt();
byte[] hashedPassword = PasswordSecurer.hashPassword(Arrays.toString(newUser.getPassword()).toCharArray(), salt);
System.out.println(Arrays.toString(hashedPassword));
if (hashedPassword == null)
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("");
if (userRepository.findByLogin(newUser.getLogin()) != null)
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("{\"errorCode\":400,\"errorMessage\":\"User already exists\"}");
System.out.println(Arrays.toString(hashedPassword));
newUser.setPassword(Arrays.toString(hashedPassword).toCharArray());
newUser.setSalt(salt);
userRepository.save(newUser);
return ResponseEntity.ok(newUser);
}
@GetMapping("/register")
public @ResponseBody
Iterable<User> getAllUsers() {
return userRepository.findAll();
}
}
在决定接受json作为请求之前,我使用byte[]作为密码,这就是它在数据库中的样子,也是我希望它现在的样子。
bAz}+øeí'méjé7héubfpléa4lypyí:'-eqé'éeó4é'6íka©§_~9w©Cx§.
但是我不能将它更改为User类中的byte[],因为Jackson会崩溃,出现错误:JSON parse error:不能从字符串反序列化byte[]
类型的值
所以我的问题是:我能做什么,使我的密码看起来再次散列,而不把char[]更改为string?
取字节数组并将其转换为base64:
byte[] bytes = {-108, -71, 126, -39, -6, 65, 50, 42, -51, 55, -88, -121, -103, 55, 109, 22, 12, -21, 33, 72, 122, -127, -31, 90, 49, 75, 90, -79, 83, -99, -50, -100, -66, 29, 45, -60, 8, 41, 1, 115, -65, -124, -5, -47, 71, -105, 28, -68, -128, 12, -111, -93, -27, -102, 51, -119, -99, 49, -23, -27, 96, -42, -128, 124, 61, -87, 17, -15, -46, -85, -16, -62, 106, -1, -79, 79, 53, 108, -56, -128};
String output = Base64.getEncoder().encodeToString(bytes);
System.out.println( "base64 is " + output );
然后你会得到:
base64 is lLl+2fpBMirNN6iHmTdtFgzrIUh6geFaMUtasVOdzpy+HS3ECCkBc7+E+9FHlxy8gAyRo+WaM4mdMenlYNaAfD2pEfHSq/DCav+xTzVsyIA=
将其作为字符串存储在数据库中,并仅与之进行比较。密码应该是一种方法--你现在需要一种方法来重置密码,以防忘记密码。
问题内容: 我的课有一个属性’PropertyA’,我希望它在序列化时在JSON对象中显示为’PropertyB’。我可以使用某种属性吗? 问题答案: 对于与使用: 确保您的课程也用属性修饰。 如果您使用的是JavaScriptSerializer,则需要创建派生的实现
我有以下Java超类,每个属性都有构造函数、getter和setter: 和一个car子类,它扩展了vehicle超类,并具有几个独特的属性: 我创建一个新的vehicle对象链表,并向其中添加一个新的car对象: 我可以用下面这样的函数更改属于vehicle超级类的任何属性: 但是当我试图创建一个类似的函数来更改其中一个子类属性时,我得到了这个错误:“方法setWheels(int)对于类型Ve
我有一个MyClass,它的属性类型为MyAttribute。该类由MySubClass继承,其属性类型为MySubAttribute。MySubAttribute是MyAttribute的子类: 现在假设我有以下代码: 如何生成MySubAttribute类型的返回值?
问题内容: 如果我尝试序列化静态属性会怎样? 谢谢 问题答案: 从这篇文章: 提示1:处理静态变量 Java类通常在静态类变量中包含一些全局相关的值。我们不会进入有关全局变量是否适当的争论的悠久历史- 只能说程序员继续发现它们有用,而纯粹主义者建议的替代方案并不总是可行的。 对于声明时初始化的静态变量,序列化不会出现任何特殊问题。第一次使用该类时,相关变量将设置为正确的值。 某些静态无法通过这种方
我是XSLT新手,希望能得到一些帮助。 我目前有一个XML,它包含以下格式的多个副本: 我的任务是替换id属性的值。我需要根据代码的数字部分改变这个值。如果值大于850000,格式应该改为USA868509。如果该值小于850000,则将id值更改为仅包括数字。XML中的其余值应保持完全相同。 我目前拥有以下xslt: 我很难确定要更改的值,因为XSLT不执行变量循环。有没有办法更改XSLT以获得