package cn.dreampie.security.credential;
import cn.dreampie.cache.SimpleCache;
import cn.dreampie.common.Constant;
import cn.dreampie.common.entity.CaseInsensitiveMap;
import cn.dreampie.security.AuthenticateService;
import cn.dreampie.security.Principal;
import java.util.*;
import static cn.dreampie.common.util.Checker.checkNotNull;
/**
* Created by ice on 14-12-24.
*/
public class Credentials {
private final AuthenticateService authenticateService;
private final long expires;
private Map<String, Map<String, Set<Credential>>> credentialMap = new CaseInsensitiveMap<Map<String, Set<Credential>>>();
private Map<String, Principal> principals = new HashMap<String, Principal>();
private long lastAccess;
public Credentials(AuthenticateService authenticateService, long expires) {
this.authenticateService = authenticateService;
checkNotNull(authenticateService, "Could not find authenticateService to load user.");
this.expires = expires;
this.lastAccess = System.currentTimeMillis() + expires;
}
public void addCredentials(Credential... credentials) {
Set<Credential> credentialSet = new HashSet<Credential>(Arrays.asList(credentials));
addCredentials(credentialSet);
}
public void addCredentials(Set<Credential> credentialSet) {
addCredentials(credentialSet, credentialMap);
}
/**
* 加倒认证map
*
* @param credentialSet 认证set
*/
private Map<String, Map<String, Set<Credential>>> setCredentials(Set<Credential> credentialSet) {
Map<String, Map<String, Set<Credential>>> credentialMap = new CaseInsensitiveMap<Map<String, Set<Credential>>>();
addCredentials(credentialSet, credentialMap);
return credentialMap;
}
private void addCredentials(Set<Credential> credentialSet, Map<String, Map<String, Set<Credential>>> credentialMap) {
Map<String, Set<Credential>> credentials;
Set<Map.Entry<String, Set<Credential>>> credentialsEntrySet;
String httpMethod;
String antPath;
int sIndex = -1;
String antPathKey;
boolean wasAdd = false;
Set<Credential> credentialDESCSet;
Map<String, Set<Credential>> credentialDESCMap;
for (Credential credential : credentialSet) {
httpMethod = credential.getHttpMethod();
antPath = credential.getAntPath();
sIndex = antPath.indexOf('*');
if (sIndex > 0) {
if (antPath.charAt(sIndex - 1) == '/') {
antPathKey = antPath.substring(0, sIndex - 1);
} else {
antPathKey = antPath.substring(0, sIndex);
}
} else {
antPathKey = antPath;
}
if (credentialMap.containsKey(httpMethod)) {
//通过httpMethod来获取认证Map
credentials = credentialMap.get(httpMethod);
credentialsEntrySet = credentials.entrySet();
for (Map.Entry<String, Set<Credential>> credentialsEntry : credentialsEntrySet) {
//如果有相同的前半部分
if (antPath.startsWith(credentialsEntry.getKey())) {
credentialsEntry.getValue().add(credential);
wasAdd = true;
break;
}
}
//如果没有找到相同前缀的
if (!wasAdd) {
if (credentials.containsKey(antPathKey)) {
credentials.get(antPathKey).add(credential);
} else {
credentialDESCSet = new TreeSet<Credential>(new CredentialASC());
credentialDESCSet.add(credential);
credentials.put(antPathKey, credentialDESCSet);
}
}
} else {
credentialDESCSet = new TreeSet<Credential>(new CredentialASC());
credentialDESCSet.add(credential);
credentialDESCMap = new TreeMap<String, Set<Credential>>(new CredentialKeyDESC());
credentialDESCMap.put(antPathKey, credentialDESCSet);
credentialMap.put(httpMethod, credentialDESCMap);
}
}
}
/**
* 取全部凭据
*
* @return 全部凭据
*/
public Map<String, Map<String, Set<Credential>>> getAllCredentials() {
if (Constant.cacheEnabled) {
//load all cache
credentialMap = SimpleCache.instance().get(Credential.CREDENTIAL_DEF_KEY, Credential.CREDENTIAL_ALL_KEY);
if (credentialMap == null) {
Set<Credential> credentialASCSet = new TreeSet<Credential>(new CredentialASC());
credentialASCSet.addAll(authenticateService.getAllCredentials());
credentialMap = setCredentials(credentialASCSet);
SimpleCache.instance().add(Credential.CREDENTIAL_DEF_KEY, Credential.CREDENTIAL_ALL_KEY, credentialMap);
}
} else {
if (credentialMap.size() <= 0 || System.currentTimeMillis() > lastAccess) {
Set<Credential> credentialASCSet = new TreeSet<Credential>(new CredentialASC());
credentialASCSet.addAll(authenticateService.getAllCredentials());
credentialMap = setCredentials(credentialASCSet);
lastAccess = System.currentTimeMillis() + expires;
}
}
//检测权限数据
checkNotNull(credentialMap, "Could not get credentials data.");
return credentialMap;
}
/**
* 取用户缓存
*
* @param username 用户名
* @return 用户
*/
public Principal getPrincipal(String username) {
Principal principal;
if (Constant.cacheEnabled) {
principal = SimpleCache.instance().get(Principal.PRINCIPAL_DEF_KEY, username);
//cache 已经失效 从接口获取用户数据
if (principal == null) {
principal = authenticateService.getPrincipal(username);
SimpleCache.instance().add(Principal.PRINCIPAL_DEF_KEY, username, principal, (int) expires);
}
} else {
boolean find = false;
if (principals.size() <= 0 || System.currentTimeMillis() > lastAccess) {
principal = authenticateService.getPrincipal(username);
principals.put(username, principal);
lastAccess = System.currentTimeMillis() + expires;
find = true;
} else {
principal = principals.get(username);
}
//如果还没有用户数据
if (!find && principal == null) {
principal = authenticateService.getPrincipal(username);
principals.put(username, principal);
}
}
return principal;
}
/**
* 删除用户缓存
*
* @param username
*/
public void removePrincipal(String username) {
if (Constant.cacheEnabled) {
SimpleCache.instance().remove(Principal.PRINCIPAL_DEF_KEY, username);
} else {
principals.remove(username);
}
}
/**
* 删除列表缓存
*/
public void removeAllCredentials() {
if (Constant.cacheEnabled) {
SimpleCache.instance().remove(Credential.CREDENTIAL_DEF_KEY, Credential.CREDENTIAL_ALL_KEY);
} else {
credentialMap.clear();
}
}
}