package security; import com.google.common.base.Strings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Arrays; import java.util.Collection; import java.util.Set; import java.util.concurrent.TimeUnit; /** * Created by nolan on 11/11/2016. * description: */ @Service public class RedisTokenManager extends AbstractTokenManager { private final String GLOBAL_TOKEN = "GLOBAL_TOKEN"; /** * Redis中Key的前缀 */ private static final String REDIS_KEY_PREFIX = "MANAGER_AUTHORIZATION_KEY_"; /** * Redis中Token的前缀 */ private static final String REDIS_TOKEN_PREFIX = "MANAGER_AUTHORIZATION_TOKEN_"; /** * Redis中账户的前缀 */ private static final String REDIS_ACCOUNT_PREFIX = "MANAGER_AUTHORIZATION_ACCOUNT_"; @Autowired private RedisTemplate<String, String> redisTemplate; /** * 踢出此账号下的所有登陆 */ @Override public void delMultiRelationshipByKey(String key) { if(Strings.isNullOrEmpty(key)) return; //获取所有登陆TOKEN Set<String> tokenSet = this.smembers(formatAccountKey(key)); if(!CollectionUtils.isEmpty(tokenSet)){ //删除这些TOKEN delete(tokenSet); //删除对应关系 delete(formatAccountKey(key)); } } @Override protected void delSingleRelationshipByKey(String key) { String token = getToken(key); if (token != null) { delete(formatKey(key), formatToken(token)); } } /** * 根据token删掉关系 * @param token */ @Override public void delRelationshipByToken(String token) { final String formatToken = formatToken(token); if (singleTokenWithUser) { String key = getKeyFromToken(token); delete(formatKey(key), formatToken); } else { //删除对应关系中的token srem(formatAccountKey(get(formatToken)),formatToken); //删除token delete(formatToken); } } /** * 创建单点登陆的登陆关系 * @param key * @param token */ @Override protected void createSingleRelationship(String key, String token) { String oldToken = get(formatKey(key)); if (oldToken != null) { delete(formatToken(oldToken)); } set(formatToken(token), key, tokenExpireSeconds); set(formatKey(key), token, tokenExpireSeconds); } /** * 创建多点登陆的登陆关系 * @param key * @param token */ @Override protected void createMultipleRelationship(String key, String token) { set(formatToken(token), key, tokenExpireSeconds); //添加到账户KEY对应的SET中 sadd(formatAccountKey(key), formatToken(token), tokenExpireSeconds); } @Override protected String getKeyByToken(String token) { return get(formatToken(token)); } @Override protected String getTokenByKey(String key) { return get(formatKey(key)); } /** * 操作后刷新登陆关系时长 * @param key * @param token */ @Override protected void flushExpireAfterOperation(String key, String token) { if (singleTokenWithUser) { expire(formatKey(key), tokenExpireSeconds); } expire(formatToken(token), tokenExpireSeconds); //刷新对应关系时长 expire(formatAccountKey(get(formatToken(token))), tokenExpireSeconds); } private String get(String key) { return redisTemplate.opsForValue().get(key); } private String set(String key, String value, int expireSeconds) { redisTemplate.opsForValue().set(key, value); redisTemplate.expire(key, expireSeconds, TimeUnit.SECONDS); return value; } /** * 添加value 对于的KEY set */ private Long sadd(String key, String value, int expireSeconds){ Long num = redisTemplate.opsForSet().add(key, value); if(0 != num){ redisTemplate.expire(key, expireSeconds, TimeUnit.SECONDS); } return num; } /** * 删除set中的某个 */ private Long srem(String key, String value){ return redisTemplate.opsForSet().remove(key,value); } /** * 获取set中所有元素 */ private Set<String> smembers(String key){ return redisTemplate.opsForSet().members(key); } private void expire(String key, int seconds) { redisTemplate.expire(key, seconds, TimeUnit.SECONDS); } private void delete(String... keys) { redisTemplate.delete(Arrays.asList(keys)); } private void delete(Collection<String> collection){ redisTemplate.delete(collection); } private String getToken(String key) { return get(formatKey(key)); } private String formatKey(String key) { return REDIS_KEY_PREFIX.concat(key); } private String formatToken(String token) { return REDIS_TOKEN_PREFIX.concat(token); } private String formatAccountKey(String key){ return REDIS_ACCOUNT_PREFIX.concat(key); } }