分布式认证授权(二)
- 微服务用户授权
在微服务中接收到网关转发过来的 Token 后,需要我们构建一个 Authentication 对象来完成微服务认证与授权,
这样这个微服务就可以根据用户所拥有的权限,来判断对应资源是否可以被用户访问
- 代码实现:在资源服务器中编写过滤器
/**
* 获取网关转发过来的请求头中保存的明文token值,用户信息
*/
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authToken = request.getHeader("auth-token");
if(StringUtils.isNotEmpty(authToken)) {
logger.info("商品资源服务器获取到token值:" + authToken);
// 解析token
// 1. 通过base64解码
String authTokenJson = new String(Base64Utils.decodeFromString(authToken));
// 2. 转成json对象
JSONObject jsonObject = JSON.parseObject(authTokenJson);
// 用户信息(用户名)
Object principal = jsonObject.get("principal");
// 请求详情
Object details = jsonObject.get("details");
// 获取用户拥有权限 sys:user:add,sys:user:edit
String authorities = ArrayUtils.toString(jsonObject.getJSONArray("authorities").toArray());
// 转为list
List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
// 自已构建一个Authentication对象,SpringSecurity就会自动进行权限判断
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(
principal, null, authorityList);
authenticationToken.setDetails(details);
// 将对象传给安全上下文,对应的就会自动的进行权限判断,同时也可以获取到用户信息
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
// 放行请求
filterChain.doFilter(request, response);
}
}
- 测试:启动认证服务器、资源服务器、网关、注册中心
# 浏览器访问如下,获取授权码
http://localhost:7001/auth/oauth/authorize?client_id=mengxuegu-pc&response_type=code
# 转发到如下地址,输入用户名+密码
http://localhost:7001/auth/login
-
使用授权码获取令牌
-
使用令牌获取资源
-
错误1
:在获取资源服务器中资源时,报错如下
-
错误原因:我在网关模块中设置了如下
-
解决方案:数据库中添加如下