SecurityContextHolder
SecurityContextHolder 是spring security 的基础工具类。这是一个工具类,只提供一些静态方法。这个工具类的目的是用来保存应用程序中当前使用人的安全上下文。将给定SecurityContext与当前执行线程关联。
官网介绍英文官网
SecurityContextHolder.getContext()
获取安全上下文SecurityContext。
安全上下文 SecurityContext
SecurityContext 可以理解成一个 存储 Authentication 的容器。Authentication 是一个用户凭证接口用来作为用户认证的凭证使用,通常常用的实现有 认证用户 UsernamePasswordAuthenticationToken 和 匿名用户AnonymousAuthenticationToken。其中 UsernamePasswordAuthenticationToken 包含了 UserDetails , AnonymousAuthenticationToken 只包含了一个字符串 anonymousUser 作为匿名用户的标识。
比如我们接受前端发起来的请求,我们在自己定义spring security 过滤器链中对每个请求进行处理。
获取用户信息和对应权限并将其封装成UsernamePasswordAuthenticationToken
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// 前端将token放在header里,每次发送请求的时候携带。
String token = request.getHeader("token");
if (token != null && !"".equals(token.trim())) {
String userName = tokenManager.getUserFromToken(token);
// 获取用户名,在redis中得到相应的权限
List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
Collection<GrantedAuthority> authorities = new ArrayList<>();
for(String permissionValue : permissionValueList) {
if(StringUtils.isEmpty(permissionValue)) continue;
// 将每一个权限值放到SimpleGrantedAuthority
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
// 用于授权
authorities.add(authority);
}
if (!StringUtils.isEmpty(userName)) {
return new UsernamePasswordAuthenticationToken(userName, token, authorities);
}
return null;
}
return null;
}
将UsernamePasswordAuthenticationToken 放入SecurityContext 中
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
logger.info("================="+req.getRequestURI());
//不是admin
if(req.getRequestURI().indexOf("admin") == -1) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = null;
try {
//获取到封装好的数据
authentication = getAuthentication(req);
} catch (Exception e) {
ResponseUtil.out(res, Result.error());
}
if (authentication != null) {
//
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
ResponseUtil.out(res, Result.error());
}
chain.doFilter(req, res);
}
重点来了我们可以在接口中通过 SecurityContextHolder 获取相应的数据
@GetMapping("info")
public Result info(){
//获取当前登录用户用户名
String username = SecurityContextHolder.getContext().getAuthentication().getName();
Map<String, Object> userInfo = indexService.getUserInfo(username);
return Result.sucess().data(userInfo);
}