文章目录

  • 一、需求分析
  • 二、服务搭建
    • 2.1 注册中心 Eureka 搭建
    • 2.2 网关 Zuul 搭建
      • 2.2.1 转发明文token给微服务
      • 2.2.2 微服务处理 token
      • 2.2.3 SpringSecurity 自定义 UserDetailsService

一、需求分析

  1. UUA认证服务负责认证授权
  2. 所有请求经过网关到达微服务
  3. 网关负责鉴权客户端以及请求的转发
  4. 网关将token解析后传给微服务,微服务进行授权

二、服务搭建

代码和环境搭建忽略,详情见:https://github.com/hucheng1997/security-oauth2

2.1 注册中心 Eureka 搭建

参考https://hucheng.blog.csdn.net/article/details/105547229

2.2 网关 Zuul 搭建

网关整合OAuth2有两种思路,一种是认证服务器生成JWT令牌,所有请求统一在网关层验证,判断权限等操作;另一种是由资源服务器处理,网关只做请求的转发。

我们选用第一种,我们把API网关作为OAuth2的资源服务器角色,实现接入客户端权限拦截,令牌解析并转发当前登录用户信息(jsonToken)给微服务,这样下游微服务就需要关心令牌格式解析以及OAuth2的相关机制。

API网关在认证授权体系里主要负责两件事:

  1. 作为OAuth2.0的资源服务器角色,实现接入方权限拦截
  2. 令牌解析并转发当前登录用户信息(明文token)给微服务

微服务拿到明文token(包含登录用户的身份和权限信息)后也需要做两件事:

  1. 用户授权拦截(看当前用户是否有权访问该资源)
  2. 将用户信息存储进当前线程上下文(有利于后续业务逻辑随时获取当前用户信息)

Zuul中定义资源服务配置,主要配置的内容就是定义一些匹配规则,描述某个接入客户端需要什么样的权限才能访问某个微服务

@Configuration
public class ResourceServerConfig {public static final String RESOURCE_ID = "res1";/*** uua令牌服务配置*/@Configuration@EnableResourceServerpublic class UUAServerConfig extends ResourceServerConfigurerAdapter {@Autowiredprivate TokenStore tokenStore;@Overridepublic void configure(ResourceServerSecurityConfigurer resources) {resources.tokenStore(tokenStore).resourceId(RESOURCE_ID).stateless(true);}@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/uua/**").permitAll();}}/*** 资源服务配置*/@Configuration@EnableResourceServerpublic class OrderServerConfig extends ResourceServerConfigurerAdapter {@Autowiredprivate TokenStore tokenStore;@Overridepublic void configure(ResourceServerSecurityConfigurer resources) {resources.tokenStore(tokenStore).resourceId(RESOURCE_ID).stateless(true);}@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/resource/**").access("#oauth2.hasScope('ALL')");}}
}

2.2.1 转发明文token给微服务

通过Zuul过滤器的方式实现,目的是让下游微服务能够很方便的获取到当前的登录用户信息(明文token

①实现Zuul前置过滤器,完成当前登录用户信息提取,并放入转发微服务的request中

*** token传递拦截*/
public class AuthFilter extends ZuulFilter {@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 0;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {/*** 获取令牌内容*/RequestContext ctx = RequestContext.getCurrentContext();//获取认证信息AuthenticationAuthentication authentication = SecurityContextHolder.getContext().getAuthentication();if (!(authentication instanceof OAuth2Authentication)) {return null;}OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) authentication;Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();/*** 组装明文token,转发给微服务,放入head中,名称为json-token*/List<String> authorities = new ArrayList<>();userAuthentication.getAuthorities().stream().forEach(s -> authorities.add(((GrantedAuthority) s).getAuthority()));OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();Map<String, String> requestParameters = oAuth2Request.getRequestParameters();Map<String,Object> jsonToken = new HashMap<>(requestParameters);if (userAuthentication!=null){jsonToken.put("principal",userAuthentication.getName());jsonToken.put("authorities",authorities);}//把身份信息和权限信息放在json中,加入http的header中,转发给微服务ctx.addZuulRequestHeader("json-token", EncryptUtil.encodeUTF8StringBase64(JSON.toJSONString(jsonToken)));return null;}
}

②将filter纳入spring 容器

@Configuration
public class ZuulConfig {/*** 注册过滤器*/@Beanpublic AuthFilter preFilter() {return new AuthFilter();}@Beanpublic FilterRegistrationBean corsFilter() {final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();final CorsConfiguration config = new CorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin("*");config.addAllowedHeader("*");config.addAllowedMethod("*");config.setMaxAge(18000L);source.registerCorsConfiguration("/**", config);CorsFilter corsFilter = new CorsFilter(source);FilterRegistrationBean bean = new FilterRegistrationBean(corsFilter);bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;}
}

2.2.2 微服务处理 token

微服务定义filter拦截token,并形成Spring Security的Authentication对象

@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("json-token");if (token != null) {String json = EncryptUtil.decodeUTF8StringBase64(token);//将token转成json对象JSONObject jsonObject = JSON.parseObject(json);UserDTO userDTO = JSON.parseObject(jsonObject.getString("principal"), UserDTO.class);//用户权限JSONArray authoritiesArray = jsonObject.getJSONArray("authorities");String[] authorities = authoritiesArray.toArray(new String[authoritiesArray.size()]);//将用户信息和权限填充 到用户身份token对象中UsernamePasswordAuthenticationToken authenticationToken= new UsernamePasswordAuthenticationToken(userDTO, null, AuthorityUtils.createAuthorityList(authorities));authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));//将authenticationToken填充到安全上下文SecurityContextHolder.getContext().setAuthentication(authenticationToken);}filterChain.doFilter(request, response);}
}

2.2.3 SpringSecurity 自定义 UserDetailsService

@Service
public class SpringDataUserDetailsService implements UserDetailsService {@AutowiredUserDao userDao;//根据 账号查询用户信息@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//将来连接数据库根据账号查询用户信息UserDto userDto = userDao.getUserByUsername(username);if(userDto == null){//如果用户查不到,返回null,由provider来抛出异常return null;}//根据用户的id查询用户的权限List<String> permissions = userDao.findPermissionsByUserId(userDto.getId());//将permissions转成数组String[] permissionArray = new String[permissions.size()];permissions.toArray(permissionArray);//将userDto转成jsonString principal = JSON.toJSONString(userDto);UserDetails userDetails = User.withUsername(principal).password(userDto.getPassword()).authorities(permissionArray).build();return userDetails;}
}

Spring Cloud Security OAuth2结合网关相关推荐

  1. 【java_wxid项目】【第七章】【Spring Cloud Security Oauth2集成】

    主项目链接:https://gitee.com/java_wxid/java_wxid 项目架构及博文总结: 点击:[使用Spring Boot快速构建应用] 点击:[使用Spring Cloud O ...

  2. gateway oauth2 对称加密_深入理解Spring Cloud Security OAuth2及JWT

    因项目需要,需要和三方的oauth2服务器进行集成.网上关于spring cloud security oauth2的相关资料,一般都是讲如何配置,而能把这块原理讲透彻的比较少,这边自己做一下总结和整 ...

  3. 玩转Spring Cloud Security OAuth2身份认证扩展——电话号码+验证码认证

    在程序的认证过程中,除了常规的用户名和密码方式(可以参考深入理解Spring Cloud Security OAuth2身份认证),也经常会出现电话号码+密码的方式:电话号码+验证码的方式:或者第三方 ...

  4. Spring Cloud Security:Oauth2实现单点登录

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录功能,本文将对其单点登录用法进行详细介绍. 单点登录简介 单 ...

  5. Spring Cloud Security:Oauth2结合JWT使用

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2还可以实现更多功能,比如使用JWT令牌存储信息,刷新令牌功能,本文将对其结合 ...

  6. Spring Cloud Security:Oauth2使用入门

    摘要 Spring Cloud Security 为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录.令牌中继.令牌交换等功能,本文将对其结合Oauth2入门使 ...

  7. 微服务集成cas_Spring Cloud(四) Spring Cloud Security集成CAS (单点登录)对微服务认证...

    一.前言 由于leader要求在搭好的spring cloud 框架中加入对微服务的认证包括单点登录认证,来确保系统的安全,所以研究了Spring Cloud Security这个组件.在前面搭好的d ...

  8. Spring Cloud入门-Oauth2授权之基于JWT完成单点登录(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 单点登录简介 创建oauth2-client模块 修改授权服务器配置 网页单点登录演示 调用接口单点登录演示 oauth2-client添加权限校 ...

  9. 「springcloud 2021 系列」Spring Cloud Gateway + OAuth2 + JWT 实现统一认证与鉴权

    通过认证服务进行统一认证,然后通过网关来统一校验认证和鉴权. 将采用 Nacos 作为注册中心,Gateway 作为网关,使用 nimbus-jose-jwt JWT 库操作 JWT 令牌 理论介绍 ...

最新文章

  1. 天之痕java版不能捉妖_〖天之痕游戏常见问题汇总(更新版)〗
  2. 2016弱校联萌十一专场10.2
  3. Boost:不受约束的集合bimap的测试程序
  4. 20170117小测
  5. wex5中集成的mysql数据库 打开时一闪而过 报错
  6. 微信小程序(看文档写实例七)微信小程序课堂宝APP实现在线课堂测试
  7. 显示计算机程序的表格如何打开,如何设置打开excel表格的一个窗口显示多标签...
  8. Google Chrome浏览器导入导出书签
  9. youtube python enty_python GUI尝鲜(但当涉猎,见往事耳)
  10. 什么是股市泡沫或楼市泡沫?泡沫何解?
  11. spanning tree增强
  12. STM32驱动AD7366-5/AD7367-5芯片
  13. 以下关于python函数说法错误的是def_以下关于Python函数的描述中,错误的是()
  14. 互联网晚报 | 10月7日 星期四 | 小米中东欧5G手机市占率排名第一;威马汽车将再获5亿美元融资;诺基亚首款平板T20发布...
  15. 数学建模之topsis法(c语言实现)
  16. 《外星人就在月球背面》值得一读
  17. 嵌入式硬盘录像机和PC电脑+视频卡录像比较
  18. mysql排列组合实现_排列-组合的代码实现
  19. 基于 Go Fyne 实现的护眼助手
  20. sql不用拼接语句实现动态查询条件

热门文章

  1. 西安交大轴承实验集XJTU-SY_Bearing_Datasets的python调用代码
  2. 计算机我的生涯规划档案,我的生涯规划档案.doc
  3. “燕云十六将”之陈丽辉(11)
  4. go mod拉取gitlab私有仓库代码问题最全总结
  5. springboot疑难杂症
  6. 最新微信QQ域名防封、微信群活码系统
  7. 大数据技术有哪些应该重点学哪些知识
  8. 老闪创业那些事儿(40)——倒霉的光哥
  9. SQL闭合方式的判断及作用
  10. 2019年—可能是我们Java程序员离危机感最近的一年!