一.登录模块具体方法
1. 根据loginParam获取User对象
1.1 发现userRepository类
1.2 观察DTO类 —> UserDTO为例
1.3 观察entity类 —> User
2. 两步验证码验证, 需要在系统设置中开启
3. 检查用户是否已经登录过了
4. 返回一个随机生成的token, 成为json对象. ----> 储存至本地内存, 以保持登录
1.1 根据loginParam获取User对象
方法run.halo.app.service.impl.AdminServiceImpl#authenticate
@Override
@NonNull
public User authenticate(@NonNull LoginParam loginParam) {
//判断输入的信息是否为空, 如果为空, 则输出message
Assert.notNull(loginParam, "Login param must not be null");
//根据loginParam获取用户名
String username = loginParam.getUsername();
String mismatchTip = "用户名或者密码不正确";
final User user;
try {
// Get user by username or email 三目运算符
user = Validator.isEmail(username) //username 判断是否为邮箱格式
//若有效,则执行第一个, 无效则执行第二个
? userService.getByEmailOfNonNull(username) :
userService.getByUsernameOfNonNull(username);
} catch (NotFoundException e) {
//有@Slf4j注解,可以直接调用log,控制台输出
log.error("Failed to find user by name: " + username);
eventPublisher.publishEvent(
new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED,
loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
//检查用户登录是否过期, 系统现在的时间和ex
userService.mustNotExpire(user);
//利用BCrypt加密算法,验证输入密码和数据库中的密码是否相同
if (!userService.passwordMatch(user, loginParam.getPassword())) {
// If the password is mismatch
eventPublisher.publishEvent(
new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED,
loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
return user;
}
getByEmailOfNonNull 方法:
run.halo.app.service.impl.UserServiceImpl#getByEmailOfNonNull
@Override
public User getByEmailOfNonNull(String email) {
return getByEmail(email).orElseThrow(
() -> new NotFoundException("The email does not exist").setErrorData(email));
}
进入getByEmail方法中
1.1.1 发现userRepository类
@Override
public Optional<User> getByEmail(String email) {
return userRepository.findByEmail(email);
}
这里出现了userRepository
public interface UserRepository extends BaseRepository<User, Integer> {}
userRepository继承了BaseRepository, BaseRepository的父类是JpaRepository
@NoRepositoryBean
public interface BaseRepository<D, I> extends JpaRepository<D, I> {}
这里是利用了Spring Data JPA, 通过简单的注解和继承关系, 实现CRUD操作
即生成DTO类( DAO类).
1.1.2 观察DTO类 —> UserDTO为例
@Data //可以根据实体类, 自动生成相关的方法 ,如get set 等方法
@ToString //重写ToString方法
@EqualsAndHashCode //重写EqualsAndHashCode方法
public class UserDTO implements OutputConverter<UserDTO, User> {
private Integer id;
private String username;
private String nickname;
private String email;
private String avatar;
private String description;
private MFAType mfaType;
private Date createTime;
private Date updateTime;
}
1.1.3 观察entity类 —> User
@Data
@Entity //JPA , 可以根据实体类, 在数据库中生成相应的表
@Table(name = "users") //表名
//子类加上@Data和@ToString(callSuper = true)两个注解, 父类也使用注解@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class User extends BaseEntity {
@Id //该变量为主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //主键类型
@Column(name = "id") //列名
private Integer id;
@Column(name = "username", length = 50, nullable = false) //列名 和 长度设置
private String username;
...
}
1.2 两步验证码验证, 需要在系统设置中开启
1.3 检查用户是否已经登录过了
1.4 返回一个随机生成的token, 成为json对象.
----> 储存至本地内存, 以保持登录
return buildAuthToken(user);
run.halo.app.service.impl.AdminServiceImpl#buildAuthToken
根据user对象,生成相应的token
@NonNull
private AuthToken buildAuthToken(@NonNull User user) {
Assert.notNull(user, "User must not be null");
// Generate new token
AuthToken token = new AuthToken();
token.setAccessToken(HaloUtils.randomUUIDWithoutDash());
token.setExpiredIn(ACCESS_TOKEN_EXPIRED_SECONDS); //24小时
token.setRefreshToken(HaloUtils.randomUUIDWithoutDash());
// Cache those tokens, just for clearing 放入缓存中
cacheStore.putAny(SecurityUtils.buildAccessTokenKey(user), token.getAccessToken(),
ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
cacheStore.putAny(SecurityUtils.buildRefreshTokenKey(user), token.getRefreshToken(),
REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
// Cache those tokens with user id
cacheStore.putAny(SecurityUtils.buildTokenAccessKey(token.getAccessToken()), user.getId(),
ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
cacheStore.putAny(SecurityUtils.buildTokenRefreshKey(token.getRefreshToken()), user.getId(),
REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
return token;
}
cacheStore是手写的缓存类
private static final ConcurrentHashMap<String, CacheWrapper<String>> CACHE_CONTAINER =
new ConcurrentHashMap<>();
用concurrentHashMap作为容器
原文链接:https://blog.csdn.net/qq_43200499/article/details/118534485