|
|
package cn.mb.cloud.auth.endpoint;
|
|
import cn.hutool.core.util.StrUtil;
|
import cn.mb.cloud.auth.security.component.MbCloudAuthUser;
|
import cn.mb.cloud.common.cache.RedisFastJsonTemplate;
|
import cn.mb.cloud.common.core.constant.SecurityConstants;
|
import cn.mb.cloud.common.core.util.ResponseData;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import lombok.AllArgsConstructor;
|
import org.springframework.cache.CacheManager;
|
import org.springframework.data.redis.core.ConvertingCursor;
|
import org.springframework.data.redis.core.Cursor;
|
import org.springframework.data.redis.core.ScanOptions;
|
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
import org.springframework.data.redis.serializer.RedisSerializer;
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.servlet.ModelAndView;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.util.ArrayList;
|
import java.util.HashSet;
|
import java.util.List;
|
|
/**
|
* @author jason
|
* 删除token端点
|
*/
|
@RestController
|
@AllArgsConstructor
|
@RequestMapping("/token")
|
public class CloudTokenEndpoint {
|
private static final String OAUTH_ACCESS_KEY_PREFIX = "oauth2_auth_to_access:";
|
private final TokenStore tokenStore;
|
private final RedisFastJsonTemplate redisTemplate;
|
private final CacheManager cacheManager;
|
|
/**
|
* 认证页面
|
*
|
* @return ModelAndView
|
*/
|
@GetMapping("/login")
|
public ModelAndView require() {
|
return new ModelAndView("ftl/login");
|
}
|
|
/**
|
* 退出token
|
*
|
* @param authHeader Authorization
|
*/
|
@PostMapping("/logout")
|
public ResponseData logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader, HttpServletRequest request) {
|
if (StrUtil.isBlank(authHeader)) {
|
return ResponseData.fail("退出失败,token 为空");
|
}
|
|
String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
|
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
|
if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
|
return ResponseData.fail("退出失败,token 无效");
|
}
|
|
OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
|
cacheManager.getCache("user_details").evict(auth2Authentication.getName());
|
tokenStore.removeAccessToken(accessToken);
|
return ResponseData.success(Boolean.TRUE);
|
}
|
|
/**
|
* 获取用户的授权码
|
*
|
* @param authHeader
|
* @return
|
*/
|
@GetMapping("user/permissions")
|
public ResponseData findUserPermissionKey(@RequestHeader(value = HttpHeaders.AUTHORIZATION,
|
required = false) String authHeader) {
|
|
if (StrUtil.isBlank(authHeader)) {
|
return ResponseData.fail("token 为空");
|
}
|
|
String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
|
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
|
if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
|
return ResponseData.fail("token 无效");
|
}
|
|
OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
|
MbCloudAuthUser mbCloudAuthUser = (MbCloudAuthUser) auth2Authentication.getPrincipal();
|
|
HashSet<String> permissions = (HashSet<String>) redisTemplate.opsForValue().
|
get(SecurityConstants.CACHE_USER_PERMISSIONS_KEY + "key:" + mbCloudAuthUser.getId());
|
return ResponseData.success(permissions);
|
}
|
|
|
/**
|
* 令牌管理调用
|
*
|
* @param token token
|
* @return
|
*/
|
@GetMapping("del/{token}")
|
public ResponseData<Boolean> delToken(@PathVariable("token") String token) {
|
OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token);
|
tokenStore.removeAccessToken(oAuth2AccessToken);
|
return ResponseData.success();
|
}
|
|
|
/**
|
* 查询token
|
*
|
* @param page 分页参数
|
* @return
|
*/
|
@GetMapping("/page")
|
public ResponseData<Page> tokenList(Page page) {
|
//根据分页参数获取对应数据
|
String key = String.format("%s*", OAUTH_ACCESS_KEY_PREFIX);
|
List<String> pages = findKeysForPage(key, page.getCurrent(), page.getSize());
|
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
page.setRecords(redisTemplate.opsForValue().multiGet(pages));
|
page.setTotal(Long.valueOf(redisTemplate.keys(key).size()));
|
return ResponseData.success(page);
|
}
|
|
|
private List<String> findKeysForPage(String patternKey, Long pageNum, Long pageSize) {
|
ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
|
RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
|
Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection
|
(redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
|
List<String> result = new ArrayList<>();
|
int tmpIndex = 0;
|
long startIndex = (pageNum - 1) * pageSize;
|
long end = pageNum * pageSize;
|
|
assert cursor != null;
|
while (cursor.hasNext()) {
|
if (tmpIndex >= startIndex && tmpIndex < end) {
|
result.add(cursor.next().toString());
|
tmpIndex++;
|
continue;
|
}
|
if (tmpIndex >= end) {
|
break;
|
}
|
tmpIndex++;
|
cursor.next();
|
}
|
return result;
|
}
|
|
|
}
|