shz.spring.token.AbstractTokenService Maven / Gradle / Ivy
package shz.spring.token;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;
import shz.core.Coder;
import shz.core.hash.MdHash;
import shz.core.msg.ServerFailureMsg;
import shz.core.security.encryption.DefaultSymmetricalEncipher;
import shz.spring.ServletHelp;
import shz.spring.auth.AuthService;
import shz.spring.session.Session;
import shz.spring.session.SessionHolder;
import javax.servlet.http.HttpServletRequest;
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.Objects;
import java.util.Optional;
public abstract class AbstractTokenService implements TokenService {
final int expireSecond;
final int delaySecond;
final String key;
final AuthService authService;
protected AbstractTokenService(int expireSecond, int delaySecond, String key, AuthService authService) {
ServerFailureMsg.requireNon(expireSecond <= 0, "生成token有效时间必须大于0");
ServerFailureMsg.requireNon(delaySecond < 0, "生成token延迟时间不能小于0");
this.expireSecond = expireSecond;
this.delaySecond = delaySecond;
this.key = key;
this.authService = authService;
}
@Override
public final String generate(Session session) {
ServerFailureMsg.requireNonNull(session.getUserid(), "生成token用户id不能为空");
ServerFailureMsg.requireNonNull(session.getRoleId(), "生成token角色id不能为空");
DefaultSymmetricalEncipher.Detail detail = encipherDetail(session.getUserid());
ServerFailureMsg.requireNonNull(detail, "用户id:%d缺少加密信息", session.getUserid());
long nowMillis = System.currentTimeMillis();
long startTimestamp = nowMillis + delaySecond * 1000L;
long endTimestamp = startTimestamp + expireSecond * 1000L;
byte[] identity = identity(session);
ByteBuffer buffer = ByteBuffer.allocate(16 + identity.length);
buffer.putLong(startTimestamp);
buffer.putLong(endTimestamp);
buffer.put(identity);
byte[] ciphertext = new DefaultSymmetricalEncipher(detail).encrypt(buffer.array());
buffer = ByteBuffer.allocate(16 + ciphertext.length);
buffer.putLong(session.getUserid());
buffer.putLong(session.getRoleId());
buffer.put(ciphertext);
String token = Base64.getEncoder().encodeToString(buffer.array());
saveIdentity(session.getUserid(), Coder.hexEncode(identity), (expireSecond + delaySecond) * 1000L);
return token;
}
protected abstract DefaultSymmetricalEncipher.Detail encipherDetail(long userid);
private byte[] identity(Session session) {
return MdHash.SHA256.hash(signData(session).getBytes());
}
@Override
public final String getToken(HttpServletRequest request) {
String token = ServletHelp.getKey(request, key);
if (token == null) return null;
if (token.startsWith("Bearer ")) return token.substring(7);
return token;
}
@Override
public final TokenIdentity getTokenIdentity(String token) {
if (token == null) return null;
TokenIdentity tokenIdentity = null;
try {
ByteBuffer buffer = ByteBuffer.wrap(Base64.getDecoder().decode(token.getBytes()));
tokenIdentity = new TokenIdentity(buffer.getLong(), buffer.getLong());
tokenIdentity.identity = new byte[buffer.remaining()];
buffer.get(tokenIdentity.identity);
} catch (Exception ignored) {
}
return tokenIdentity;
}
@Override
public final TokenIdentity getTokenIdentity(HttpServletRequest request) {
return getTokenIdentity(getToken(request));
}
@Override
public final TokenInfo getTokenInfo(TokenIdentity tokenIdentity) {
if (tokenIdentity == null) return null;
TokenInfo info = new TokenInfo();
info.setUserid(tokenIdentity.userid);
info.setRoleId(tokenIdentity.roleId);
try {
DefaultSymmetricalEncipher.Detail detail = encipherDetail(info.getUserid());
if (detail != null) {
ByteBuffer buffer = ByteBuffer.wrap(new DefaultSymmetricalEncipher(detail).decrypt(tokenIdentity.identity));
info.setStartTimestamp(buffer.getLong());
info.setEndTimestamp(buffer.getLong());
byte[] identity = new byte[buffer.remaining()];
buffer.get(identity);
info.setIdentity(Coder.hexEncode(identity));
}
} catch (Exception ignored) {
}
return info;
}
@Override
public final TokenInfo getTokenInfo(HttpServletRequest request) {
return getTokenInfo(getTokenIdentity(request));
}
@Override
public final boolean verify(TokenInfo tokenInfo, Session session) {
if (tokenInfo == null || tokenInfo.getIdentity() == null) return false;
long nowMillis = System.currentTimeMillis();
if (tokenInfo.getStartTimestamp() > nowMillis || tokenInfo.getEndTimestamp() < nowMillis) return false;
return Objects.equals(Coder.hexEncode(identity(session)), tokenInfo.getIdentity());
}
@Override
public final boolean isLogin(TokenInfo tokenInfo) {
return Objects.equals(getIdentity(tokenInfo.getUserid()), tokenInfo.getIdentity());
}
@Override
public final boolean isLogin(Session session) {
return session.getUserid() != null && Objects.equals(getIdentity(session.getUserid()), Coder.hexEncode(identity(session)));
}
@Override
public final void logout(Long userid) {
if (userid != null) {
Session session = SessionHolder.get();
if (session != null) {
authService.checkUserPermission(session.getUserid(), session.getRoleId(), userid);
deleteIdentity(userid);
}
}
}
@Override
public final void logout() {
Session session = SessionHolder.get();
if (session != null) {
Long userid = session.getUserid();
if (userid != null) deleteIdentity(userid);
}
}
@Override
public final boolean refresh(Long userid) {
if (userid == null) return false;
Session session = SessionHolder.get();
if (session == null) return false;
authService.checkUserPermission(session.getUserid(), session.getRoleId(), userid);
return expireIdentity(userid, expireSecond * 1000L);
}
@Override
public final boolean refresh() {
Session session = SessionHolder.get();
return session != null && session.getUserid() != null && expireIdentity(session.getUserid(), expireSecond * 1000L);
}
@Override
public String signData(Session session) {
return session.getIp() + "-" +
session.getMac() + "-" +
session.getBrowser() + "-" +
session.getBrowserVersion() + "-" +
session.getOs();
}
@Override
public String signData(HttpServletRequest request) {
UserAgent userAgent = ServletHelp.getUserAgent(request);
return ServletHelp.getIp(request) + "-" +
request.getHeader("Mac") + "-" +
Optional.ofNullable(userAgent.getBrowser()).map(Browser::getName).orElse(null) + "-" +
Optional.ofNullable(userAgent.getBrowserVersion()).map(Version::getVersion).orElse(null) + "-" +
Optional.ofNullable(userAgent.getOperatingSystem()).map(OperatingSystem::getName).orElse(null);
}
protected abstract void saveIdentity(long userid, String identity, long expireMillis);
protected abstract String getIdentity(long userid);
protected abstract void deleteIdentity(long userid);
protected abstract boolean expireIdentity(long userid, long expireMillis);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy