15 changed files with 68 additions and 559 deletions
@ -1,68 +0,0 @@ |
|||||
package com.dreamchaser.depository_manage.security.bean; |
|
||||
|
|
||||
import com.dreamchaser.depository_manage.entity.User; |
|
||||
import com.dreamchaser.depository_manage.exception.MyException; |
|
||||
import com.dreamchaser.depository_manage.security.pool.AuthenticationTokenPool; |
|
||||
import com.dreamchaser.depository_manage.service.UserService; |
|
||||
import com.dreamchaser.depository_manage.utils.Md5; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.stereotype.Component; |
|
||||
|
|
||||
/** |
|
||||
* 内置多种登录方式,和shiro中的realm类似 |
|
||||
*/ |
|
||||
@Component |
|
||||
public class LoginRealms { |
|
||||
@Autowired |
|
||||
private UserService userService; |
|
||||
|
|
||||
/** |
|
||||
* 认证,如果认证成功则返回凭证,否则返回null |
|
||||
* @param userToken 未认证的令牌 |
|
||||
* @return 如果认证成功则返回凭证,否则返回null |
|
||||
*/ |
|
||||
public String authenticate(UserToken userToken){ |
|
||||
if (userToken.getCredentials()!=null){ |
|
||||
//对密码加密
|
|
||||
userToken.setCredentials(Md5.crypt(userToken.getCredentials())); |
|
||||
} |
|
||||
if (userToken.getLoginType().equals(LoginType.EMAIl_PASSWORD)){ |
|
||||
return handle(userToken,emailLogin(userToken)); |
|
||||
} |
|
||||
//else if (其他登录方式...)
|
|
||||
//如果无匹配的认证方式则视为验证失败
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 邮箱登录方式 |
|
||||
* @param userToken 令牌 |
|
||||
* @return 认证成功返回SimpleUser |
|
||||
*/ |
|
||||
private User emailLogin(UserToken userToken){ |
|
||||
return userService.findUserById(userToken.getPrincipal()); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 根据传入的user是否为null(是否认证通过)来对令牌做剩下的操作(将user刻入令牌,并将该令牌放入令牌池中) |
|
||||
* @param userToken 经过验证后的令牌 |
|
||||
* @return token 根据令牌生成的凭证 ,如果认证未成功则返回null |
|
||||
*/ |
|
||||
private String handle(UserToken userToken,User user){ |
|
||||
if (user==null){ |
|
||||
//说明账户不存在
|
|
||||
throw new MyException(409,"该用户不存在,请注册后再登录!"); |
|
||||
} |
|
||||
//判断密码是否正确
|
|
||||
if (user.getPwd().equals(userToken.getCredentials())){ |
|
||||
//将UserP信息刻入令牌
|
|
||||
userToken.setUser(userService.singlePack(user)); |
|
||||
//获取token凭证
|
|
||||
String token=Md5.crypt(userToken.getPrincipal()+userToken.getInstant()); |
|
||||
//将令牌放入认证令牌池
|
|
||||
// AuthenticationTokenPool.addToken(token,userToken);
|
|
||||
return token; |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
package com.dreamchaser.depository_manage.security.bean; |
|
||||
|
|
||||
/** |
|
||||
* 登录方式枚举类 |
|
||||
* @author 金昊霖 |
|
||||
*/ |
|
||||
|
|
||||
public enum LoginType { |
|
||||
/** |
|
||||
* 通用 |
|
||||
*/ |
|
||||
COMMON("common_realm"), |
|
||||
/** |
|
||||
* 用户密码登录 |
|
||||
*/ |
|
||||
EMAIl_PASSWORD("user_password_realm"), |
|
||||
/** |
|
||||
* 手机验证码登录 |
|
||||
*/ |
|
||||
USER_PHONE("user_phone_realm"), |
|
||||
/** |
|
||||
* 第三方登录(微信登录) |
|
||||
*/ |
|
||||
WECHAT_LOGIN("wechat_login_realm"), |
|
||||
/** |
|
||||
* 第三方登录(qq登录) |
|
||||
*/ |
|
||||
QQ_LOGIN("qq_login_realm"); |
|
||||
|
|
||||
|
|
||||
private String type; |
|
||||
|
|
||||
LoginType(String type) { |
|
||||
this.type = type; |
|
||||
} |
|
||||
|
|
||||
public String getType() { |
|
||||
return type; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 根据简单的字符串返回对应的LoginType |
|
||||
* @param s 简单的字符串 |
|
||||
* @return 对应的LoginType |
|
||||
*/ |
|
||||
public static LoginType getType(String s){ |
|
||||
switch (s) { |
|
||||
case "email": |
|
||||
return EMAIl_PASSWORD; |
|
||||
case "qq": |
|
||||
return QQ_LOGIN; |
|
||||
case "wechat": |
|
||||
return WECHAT_LOGIN; |
|
||||
case "phone": |
|
||||
return USER_PHONE; |
|
||||
default: |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public String toString() { |
|
||||
return this.type; |
|
||||
} |
|
||||
} |
|
||||
@ -1,88 +0,0 @@ |
|||||
package com.dreamchaser.depository_manage.security.bean; |
|
||||
|
|
||||
|
|
||||
import com.dreamchaser.depository_manage.entity.User; |
|
||||
import com.dreamchaser.depository_manage.pojo.UserP; |
|
||||
import lombok.Data; |
|
||||
|
|
||||
import java.time.Instant; |
|
||||
|
|
||||
|
|
||||
/** |
|
||||
* 登录令牌,默认有效期为7天 |
|
||||
* @author 金昊霖 |
|
||||
*/ |
|
||||
@Data |
|
||||
public class UserToken{ |
|
||||
|
|
||||
final long DEFAULT_TERM=60*60*24*7; |
|
||||
/** |
|
||||
* 登录方式 |
|
||||
*/ |
|
||||
private LoginType loginType; |
|
||||
/** |
|
||||
* 微信、qq的code,邮箱,或者用户名之类的 |
|
||||
*/ |
|
||||
private String principal; |
|
||||
|
|
||||
/** |
|
||||
* 相当于密码(一般是加密过的) |
|
||||
*/ |
|
||||
private String credentials; |
|
||||
|
|
||||
/** |
|
||||
* 放入的时间 |
|
||||
*/ |
|
||||
private Instant instant; |
|
||||
|
|
||||
/** |
|
||||
* 有效期(单位:秒) |
|
||||
*/ |
|
||||
private long term; |
|
||||
|
|
||||
/** |
|
||||
* 可以放一些不敏感的信息,以便下次访问时可以直接取出,如果user属性太多可以另外写个类,比如SimpleUser, |
|
||||
* 存放一些经常需要用到的信息。 |
|
||||
*/ |
|
||||
private UserP User; |
|
||||
|
|
||||
/** |
|
||||
* 根据时间判断是否有效 |
|
||||
* @return 有效则返回true,否则返回false |
|
||||
*/ |
|
||||
public boolean isValid(){ |
|
||||
return Instant.now().getEpochSecond()-instant.getEpochSecond()<=term; |
|
||||
} |
|
||||
|
|
||||
public UserToken(LoginType loginType, String principal, String credentials, Instant instant, long term, UserP user) { |
|
||||
this.loginType = loginType; |
|
||||
this.principal = principal; |
|
||||
this.credentials = credentials; |
|
||||
this.instant = instant; |
|
||||
this.term = term; |
|
||||
this.User = user; |
|
||||
} |
|
||||
|
|
||||
public UserToken(LoginType loginType, String principal, String credentials, Instant instant, long term) { |
|
||||
this.loginType = loginType; |
|
||||
this.principal = principal; |
|
||||
this.credentials = credentials; |
|
||||
this.instant = instant; |
|
||||
this.term = term; |
|
||||
} |
|
||||
|
|
||||
public UserToken(LoginType loginType, String principal, String credentials) { |
|
||||
this.loginType = loginType; |
|
||||
this.principal = principal; |
|
||||
this.credentials = credentials; |
|
||||
this.instant = Instant.now(); |
|
||||
this.term=DEFAULT_TERM; |
|
||||
} |
|
||||
|
|
||||
public UserToken(LoginType loginType, String principal) { |
|
||||
this.loginType = loginType; |
|
||||
this.principal = principal; |
|
||||
this.instant=Instant.now(); |
|
||||
this.term=DEFAULT_TERM; |
|
||||
} |
|
||||
} |
|
||||
@ -1,74 +0,0 @@ |
|||||
package com.dreamchaser.depository_manage.security.bean; |
|
||||
|
|
||||
import lombok.Data; |
|
||||
|
|
||||
import java.time.Instant; |
|
||||
import java.util.Random; |
|
||||
|
|
||||
/** |
|
||||
* 验证码,默认有效期为五分钟 |
|
||||
* @author 金昊霖 |
|
||||
*/ |
|
||||
@Data |
|
||||
public class VerificationCode { |
|
||||
/** |
|
||||
* 默认持续时间 |
|
||||
*/ |
|
||||
private final long DEFAULT_TERM=60*5; |
|
||||
/** |
|
||||
* 验证码 |
|
||||
*/ |
|
||||
private String code; |
|
||||
/** |
|
||||
* 创建时刻 |
|
||||
*/ |
|
||||
private Instant instant; |
|
||||
/** |
|
||||
* 有效期 |
|
||||
*/ |
|
||||
private long term; |
|
||||
|
|
||||
/** |
|
||||
* 根据时间判断是否有效 |
|
||||
* @return boolean值 |
|
||||
*/ |
|
||||
public boolean isValid(){ |
|
||||
return Instant.now().getEpochSecond()-instant.getEpochSecond()<=term; |
|
||||
} |
|
||||
|
|
||||
public VerificationCode(Instant instant, long term) { |
|
||||
//生成随机验证码code
|
|
||||
generateCode(); |
|
||||
this.instant = instant; |
|
||||
this.term = term; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public VerificationCode(Instant instant) { |
|
||||
//生成随机验证码code
|
|
||||
generateCode(); |
|
||||
this.instant = instant; |
|
||||
this.term=DEFAULT_TERM; |
|
||||
} |
|
||||
|
|
||||
public VerificationCode() { |
|
||||
//生成随机验证码code
|
|
||||
generateCode(); |
|
||||
this.instant=Instant.now(); |
|
||||
this.term=DEFAULT_TERM; |
|
||||
} |
|
||||
|
|
||||
private void generateCode(){ |
|
||||
StringBuilder codeNum = new StringBuilder(); |
|
||||
int [] numbers = {0,1,2,3,4,5,6,7,8,9}; |
|
||||
Random random = new Random(); |
|
||||
for (int i = 0; i < 5; i++) { |
|
||||
//目的是产生足够随机的数,避免产生的数字重复率高的问题
|
|
||||
int next = random.nextInt(10000); |
|
||||
codeNum.append(numbers[next % 10]); |
|
||||
} |
|
||||
this.code= codeNum.toString(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
@ -1,54 +0,0 @@ |
|||||
package com.dreamchaser.depository_manage.security.pool; |
|
||||
|
|
||||
import com.dreamchaser.depository_manage.security.bean.VerificationCode; |
|
||||
|
|
||||
import java.util.Map; |
|
||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||
|
|
||||
/** |
|
||||
* 验证码等待池 |
|
||||
* @author 金昊霖 |
|
||||
*/ |
|
||||
public class VerificationCodePool { |
|
||||
private static Map<String, VerificationCode> pool=new ConcurrentHashMap<>(10); |
|
||||
|
|
||||
/** |
|
||||
* 增加一条验证码 |
|
||||
* @param principal 主要内容,如邮箱,电话号码等 |
|
||||
* @param verificationCode 验证码 |
|
||||
*/ |
|
||||
public static void addCode(String principal,VerificationCode verificationCode){ |
|
||||
pool.put(principal, verificationCode); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 根据principal主要信息获取未过期的验证码,如果没有未过期的令牌则返回null |
|
||||
* @param principal 主要内容,如邮箱,电话号码等 |
|
||||
* @return verificationCode 未过期的验证码或者null |
|
||||
*/ |
|
||||
public static VerificationCode getCode(String principal){ |
|
||||
VerificationCode verificationCode=pool.get(principal); |
|
||||
|
|
||||
//如果没有相应验证码则直接返回null
|
|
||||
if (verificationCode==null){ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
//判断令牌是否过期
|
|
||||
if (verificationCode.isValid()){ |
|
||||
return verificationCode; |
|
||||
}else{ |
|
||||
//清除过期验证码
|
|
||||
pool.remove(principal); |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 根据主要信息principal删除对应的验证码 |
|
||||
* @param principal 主要信息 |
|
||||
*/ |
|
||||
public static void removeCode(String principal){ |
|
||||
pool.remove(principal); |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue