1、pom.xml
<parent>
<artifactId>common-service</artifactId>
<groupId>com.ggyy</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Common Service -->
<dependency>
<groupId>com.ggyy</groupId>
<artifactId>common-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Repository Service -->
<dependency>
<groupId>com.southwind</groupId>
<artifactId>repository-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- 解决Jwt的JDK版本问题 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
2、application.yml
server:
port: 8084
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/uushop
username: root
password: 123456
application:
name: account-service
redis:
database: 0
host: 192.168.248.138
port: 6379
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: com/southwind/mapper/xml/*.xml
3、entity 实体类
Admin
@Data
@EqualsAndHashCode(callSuper = false)
public class Admin implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "admin_id", type = IdType.AUTO)
private Integer adminId;
/**
* 账号
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 用户头像
*/
private String imgUrl;
/**
* 用户名称
*/
private String name;
}
User
@Data
@EqualsAndHashCode(callSuper = false)
public class User implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "user_id", type = IdType.AUTO)
private Integer userId;
private String mobile;
private String password;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
4、用户注册
From–>UserRegisterForm 数据校验
@Data
public class UserRegisterForm {
@NotEmpty(message = "电话不能为空")
private String mobile;
@NotEmpty(message = "校验码不能为空")
private String code;
@NotEmpty(message = "密码不能为空")
private String password;
}
util—》MD5Util 加盐加密
public class MD5Util {
/**
* byte[]字节数组 转换成 十六进制字符串
*
* @param arr 要转换的byte[]字节数组
*
* @return String 返回十六进制字符串
*/
private static String hex(byte[] arr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; ++i) {
sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}
/**
* MD5加密,并把结果由字节数组转换成十六进制字符串
*
* @param str 要加密的内容
*
* @return String 返回加密后的十六进制字符串
*/
private static String md5Hex(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
return hex(digest);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
return "";
}
}
/**
* 生成含有随机盐的密码
*
* @param password 要加密的密码
*
* @return String 含有随机盐的密码
*/
public static String getSaltMD5(String password) {
// 生成一个16位的随机数
Random random = new Random();
StringBuilder sBuilder = new StringBuilder(16);
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
int len = sBuilder.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sBuilder.append("0");
}
}
// 生成最终的加密盐
String salt = sBuilder.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return String.valueOf(cs);
}
/**
* 验证加盐后是否和原密码一致
*
* @param password 原密码
*
* @param password 加密之后的密码
*
*@return boolean true表示和原密码一致 false表示和原密码不一致
*/
public static boolean getSaltverifyMD5(String password, String md5str) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5str.charAt(i);
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
cs2[i / 3] = md5str.charAt(i + 1);
}
String Salt = new String(cs2);
return md5Hex(password + Salt).equals(String.valueOf(cs1));
}
public static void main(String[] args) {
// 原密码
String plaintext = "123456";
String s1 = MD5Util.getSaltMD5(plaintext);
System.out.println(s1);
// String s = MD5Util.getSaltMD5(plaintext);
// System.out.println(s);
// 获取加盐后的MD5值
// String ciphertext = MD5Util.getSaltMD5(plaintext);
// System.out.println("加盐后MD5:" + ciphertext);
// System.out.println("是否是同一字符串:" + MD5Util.getSaltverifyMD5(plaintext, ciphertext));
// System.out.println(MD5Util.getSaltverifyMD5(plaintext, "c1df1b61022d11d41829f63a08ff5824427f40af83919878"));
}
}
controller
校验手机号的时候用了 common–server下的
RegexValidateUtil.checkMobile
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/register")
public ResultVO register(@Valid @RequestBody UserRegisterForm userRegisterForm, BindingResult bindingResult){
if(bindingResult.hasErrors()){
throw new ShopException(ResponseEnum.USER_INFO_NULL.getMsg());
}
//判断手机号是否正确
Assert.isTrue(RegexValidateUtil.checkMobile(userRegisterForm.getMobile()), ResponseEnum.MOBILE_ERROR);
//判断手机号是否已经注册
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mobile", userRegisterForm.getMobile());
User one = this.userService.getOne(queryWrapper);
if(one!=null){
throw new ShopException(ResponseEnum.USER_MOBILE_EXIST.getMsg());
}
String code = (String) this.redisTemplate.opsForValue().get("uushop-sms-code-" + userRegisterForm.getMobile());
//状态码比较--枚举
Assert.equals(code, userRegisterForm.getCode(), ResponseEnum.USER_CODE_ERROR);
//注册
User user = new User();
user.setMobile(userRegisterForm.getMobile());
user.setPassword(MD5Util.getSaltMD5(userRegisterForm.getPassword()));
//存数据
boolean save = this.userService.save(user);
if(save) return ResultVOUtil.success(null);
return ResultVOUtil.fail(null);
}
}
5、用户登录
form–》UserLoginForm 非空校验
@Data
public class UserLoginForm {
@NotEmpty(message = "电话不能为空")
private String mobile;
@NotEmpty(message = "密码不能为空")
private String password;
}
vo–>UserVO
@Data
public class UserVO {
private Integer userId;
private String mobile;
private String password;
private String token;
}
util–>JWT生成token
jwt --基于web的验证机制(令牌)
public class JwtUtil {
//有限时间(毫秒)
private static long tokenExpiration = 1000 * 60 * 60 * 24;
private static String tokenSignKey = "a1d23mi789n";
//加密
public static String createToken(Integer id,String mobile){
String token = Jwts.builder()
//载荷:自定义信息
.claim("id", id)
.claim("mobile", mobile)
//载荷:默认信息
.setSubject("uushop-user") //令牌主题
//现在事件+有限时间
.setExpiration(new Date(System.currentTimeMillis()+tokenExpiration)) //过期时间
.setId(UUID.randomUUID().toString())
//签名哈希
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
//组装jwt字符串----
.compact();
return token;
}
//解密(判断有没有异常)
public static boolean checkToken(String token){
if(StringUtils.isEmpty(token)){ //非空
return false;
}
try {
//通过密钥解密
//正常,没报错---token是对的
//解密,报错--错
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
} catch (Exception e) {
return false;
}
return true;
}
//测试
public static void main(String[] args) {
//①生成token
// String token = JwtUtil.createToken(26, "13998786612");
// System.out.println(token);
//②复制--校验
String token = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MjYsIm1vYmlsZSI6IjEzOTk4Nzg2NjEyIiwic3ViIjoidXVzaG9wLXVzZXIiLCJleHAiOjE2MzM3ODQ4MDksImp0aSI6IjIwNTY2ZjlhLTU3MDMtNDc5My1hNjRmLTRkOGJmMjcyMjRjYSJ9.J-4qI1CACtF0g_zEZ22D7IiahIGX4Z3qgpxn0vtdTUM";
//③checkToken验证
boolean b = JwtUtil.checkToken(token);
System.out.println(b);
}
在这里插入代码片
controller
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/login")
public ResultVO login(@Valid UserLoginForm userLoginForm,BindingResult bindingResult){
if(bindingResult.hasErrors()){
throw new ShopException(ResponseEnum.USER_INFO_NULL.getMsg());
}
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("mobile", userLoginForm.getMobile());
User one = this.userService.getOne(queryWrapper);
if(one == null){
throw new ShopException(ResponseEnum.USER_MOBILE_NULL.getMsg());
}
boolean saltverifyMD5 = MD5Util.getSaltverifyMD5(userLoginForm.getPassword(), one.getPassword());
if(!saltverifyMD5){
throw new ShopException(ResponseEnum.PASSWORD_ERROR.getMsg());
}
UserVO userVO = new UserVO();
userVO.setMobile(one.getMobile());
userVO.setUserId(one.getUserId());
userVO.setPassword(one.getPassword());
userVO.setToken(JwtUtil.createToken(one.getUserId(), one.getMobile()));
return ResultVOUtil.success(userVO);
}
}
token验证
controller
@GetMapping("/checkToken")
public ResultVO checkToken(HttpServletRequest request){
String token = request.getHeader("token");
boolean b = JwtUtil.checkToken(token);
if(b) return ResultVOUtil.success(null);
return ResultVOUtil.fail(null);
}