范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

使用SpringSecurity资源服务器来保护SpringCloud微服务

  今天我将用实际例子来演示单体应用改造为Spring Cloud微服务时的资源服务器实现。  资源服务器改造
  以Spring Security实战干货的DEMO为例子,原本它是一个单体应用,认证和授权都在一个应用中使用。改造为独立的服务后,原本的认证就要剥离出去(这个后续再讲如何实现),服务将只保留基于用户凭证(JWT)的访问控制功能。接下来我们将一步步来实现该能力。  所需依赖
  在Spring Security的基础上,我们需要加入新的依赖来支持OAuth2 Resource Server和JWT。我们需要引入下面几个依赖库:                       org.springframework.boot             spring-boot-starter-security                                        org.springframework.security             spring-security-oauth2-resource-server                                       org.springframework.security             spring-security-oauth2-jose          ❝
  Spring Security 5.x 移除了OAuth2.0授权服务器,保留了OAuth2.0资源服务器。 JWT解码
  要校验JWT就必须实现对JWT的解码功能,在Spring Security OAuth2 Resource Server模块中,默认提供了解码器,这个解码器需要调用基于:  spring.security.oauth2.resourceserver
  配置下的元数据来生成解码配置,这里的配置大部分是调用授权服务器开放的 well-known 断点,包含了解析验证JWT一系列参数: jwkSetUri  一般是授权服务器提供的获取JWK配置的well-known 端点,用来校验JWT Token。 jwsAlgorithm  指定jwt使用的算法,默认 RSA-256 。 issuerUri  获取OAuth2.0 授权服务器元数据的端点。 publicKeyLocation  用于解码的公钥路径,作为资源服务器来说将只能持有公钥,不应该持有私钥。
  为了实现平滑过渡,默认的配置肯定不能用了,需要定制化一个JWT解码器。接下来我们一步步来实现它。  分离公私钥
  资源服务器只能保存公钥,所以需要从之前的 jks 文件中导出一个公钥。  keytool -export -alias felordcn -keystore   -file <导出cer的全路径>
  例如:   keytool -export -alias felordcn -keystore D:keystoresfelordcn.jks  -file d:keystorespublickey.cer
  把分离的 cer 公钥文件放到原来jks 文件的路径下面,资源服务器不再保存jks 。 自定义jwt解码器
  spring-security-oauth2-jose 是Spring Security的jose规范依赖。我将根据该类库来实现自定义的JWT解码器。     /**      * 基于Nimbus的jwt解码器,并增加了一些自定义校验策略      *      * @param validator the validator      * @return the jwt decoder      */     @SneakyThrows     @Bean     public JwtDecoder jwtDecoder(@Qualifier("delegatingTokenValidator") DelegatingOAuth2TokenValidator validator) {         CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");         // 从classpath路径读取cer公钥证书来配置解码器         ClassPathResource resource = new ClassPathResource(this.jwtProperties.getCertInfo().getPublicKeyLocation());         Certificate certificate = certificateFactory.generateCertificate(resource.getInputStream());         PublicKey publicKey = certificate.getPublicKey();         NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder.withPublicKey((RSAPublicKey) publicKey).build();         nimbusJwtDecoder.setJwtValidator(validator);         return nimbusJwtDecoder;     }
  上面的解码器基于我们的公钥证书,同时我还自定义了一些校验策略。不得不说Nimbus的jwt类库比jjwt要好用的多。  自定义资源服务器配置
  接下来配置资源服务器。  核心流程和概念
  资源服务器其实也就是配置了一个过滤器 BearerTokenAuthenticationFilter 来拦截并验证Bearer Token。验证通过而且权限符合要求就放行,不通过就不放行。
  和之前不太一样的是验证成功后凭据不再是 UsernamePasswordAuthenticationToken 而是JwtAuthenticationToken : @Transient public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationToken {   private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;   private final String name;   /**   * Constructs a {@code JwtAuthenticationToken} using the provided parameters.   * @param jwt the JWT   */  public JwtAuthenticationToken(Jwt jwt) {   super(jwt);   this.name = jwt.getSubject();  }   /**   * Constructs a {@code JwtAuthenticationToken} using the provided parameters.   * @param jwt the JWT   * @param authorities the authorities assigned to the JWT   */  public JwtAuthenticationToken(Jwt jwt, Collection<? extends GrantedAuthority> authorities) {   super(jwt, authorities);   this.setAuthenticated(true);   this.name = jwt.getSubject();  }   /**   * Constructs a {@code JwtAuthenticationToken} using the provided parameters.   * @param jwt the JWT   * @param authorities the authorities assigned to the JWT   * @param name the principal name   */  public JwtAuthenticationToken(Jwt jwt, Collection<? extends GrantedAuthority> authorities, String name) {   super(jwt, authorities);   this.setAuthenticated(true);   this.name = name;  }   @Override  public Map getTokenAttributes() {   return this.getToken().getClaims();  }   /**   * jwt 中的sub 值  用户名比较合适   */  @Override  public String getName() {   return this.name;  }  }
  这个我们改造的时候要特别注意,尤其是从 SecurityContext 获取的时候用户凭证信息的时候。 资源管理器配置
  从Spring Security 5的某版本开始不需要再集成适配类了,只需要这样就能配置Spring Security,资源管理器也是这样:      @Bean     SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {         return http.authorizeRequests(request -> request.anyRequest()                         .access("@checker.check(authentication,request)"))                 .exceptionHandling()                 .accessDeniedHandler(new SimpleAccessDeniedHandler())                 .authenticationEntryPoint(new SimpleAuthenticationEntryPoint())                 .and()                 .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)                 .build();     }
  这里只需要声明使用JWT校验的资源服务器,同时配置好定义的 401 端点和403 处理器即可。这里我加了基于SpEL的动态权限控制,这个再以往都讲过了,这里不再赘述。 JWT个性化解析
  从JWT Token中解析数据并生成 JwtAuthenticationToken 的操作是由JwtAuthenticationConverter 来完成的。你可以定制这个转换器来实现一些个性化功能。比如默认情况下解析出来的权限都是带SCOPE_ 前缀的,而项目用ROLE_ ,你就可以通过这个类兼容一下老项目。      @Bean     JwtAuthenticationConverter jwtAuthenticationConverter() {         JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();         JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); //        如果不按照规范  解析权限集合Authorities 就需要自定义key //        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("scopes"); //        OAuth2 默认前缀是 SCOPE_     Spring Security 是 ROLE_         jwtGrantedAuthoritiesConverter.setAuthorityPrefix("");         jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);         // 设置jwt中用户名的key  默认就是sub  你可以自定义         jwtAuthenticationConverter.setPrincipalClaimName(JwtClaimNames.SUB);         return jwtAuthenticationConverter;     }
  这里基本上就改造完成了。你受保护的资源API将由Bearer Token来保护。  ❝
  在实际生产中建议把资源服务器封装为依赖集成到需要保护资源的的服务中即可。 附加说明
  为了测试资源服务器,假设我们有一个颁发令牌的授权服务器。这里简单模拟了一个发令牌的方法用来获取Token:      /**      * 资源服务器不应该生成JWT 但是为了测试 假设这是个认证服务器      */     @SneakyThrows     @Test     public void imitateAuthServer() {          JwtEncoder jwsEncoder = new NimbusJwsEncoder(jwkSource());          JwtTokenGenerator jwtTokenGenerator = new JwtTokenGenerator(jwsEncoder);         OAuth2AccessTokenResponse oAuth2AccessTokenResponse = jwtTokenGenerator.tokenResponse();          System.out.println("oAuth2AccessTokenResponse = " + oAuth2AccessTokenResponse.getAccessToken().getTokenValue());     }              @SneakyThrows     private JWKSource jwkSource() {         ClassPathResource resource = new ClassPathResource("felordcn.jks");         KeyStore jks = KeyStore.getInstance("jks");         String pass = "123456";         char[] pem = pass.toCharArray();         jks.load(resource.getInputStream(), pem);          RSAKey rsaKey = RSAKey.load(jks, "felordcn", pem);          JWKSet jwkSet = new JWKSet(rsaKey);         return new ImmutableJWKSet<>(jwkSet);     }

咆哮而来的新法式浪漫,你准备好了吗?在盛开的樱花树下,来一组美美的自拍浪漫气息满分,坐在午后的窗边看细碎阳光扫在书页上,手边茶香氤氲又是另一种散漫的自由那么今天,来看点不一样的霸气的新法式浪漫,带你get最新享受新法抖音壁纸2月19日我就喜欢你看不惯我,又干不掉我的样子一加9和OPPOFindX3相比较,该如何选择?如果非要在这两款手机中选择一款手机进行购买,小芳我个人是会选择OPPOFindX3这款手机会更多一些。我给到的理由有以下几点,大家不妨参考一下。理由一首先在屏幕质量方面,OPPOF小米11青春版OPPOReno5iQOOneo5和红米K40之间怎么选?如果非要在这四款手机中选择一款手机进行购买,小芳我个人会更加倾向于红米K40这款手机会更多一些。我给到的理由有以下几点,大家不妨参考一下。理由一首先从价格方面角度来说,在相同内存配一加9RT和nova9Pro价格差不多,到底买谁好?现在已经是2021年了,还买什么4G手机呢?正是因为个这个原因,小芳是不建议大家购买nova9Pro这款手机的。也许小芳做出这样的结论会过于草率,所以为了让小芳的结论更加的有说服力真我gt大师探索版和opporeno5pro相比较,该如何选择?如果非要在这两款手机中选择一款手机进行购买,小芳我个人会更加倾向于性价比更高的真我gt大师探索版这款手机会更多一些。我给到的理由有以下几点,大家不妨参考一下。理由一首先从一款手机的荣耀50和华为nova8相比较,该如何选择?如果非要在这两款手机中选择一款手机进行购买,小芳我个人是更加倾向于荣耀50这款手机会更多一些的。我给到的理由有以下几点,大家不妨参考一下。理由一荣耀50这款手机的性能是会比华为no华为nova9Pro和魅族18S价格差不多,买哪款好?虽然两款手机的价格差不多,但是呢,很明显购买魅族18S这款手机的性价比会比华为nova9Pro这款手机更高。就小芳个人而言,我是会更加倾向于性价比更高的魅族18S这款手机的。不过话iQOOz5和红米K40游戏增强版之间,该如何抉择?其实这两款手机是非常好选择的,因为两款手机的目标顾客人群是不一样的。iQOOz5这款手机的目标顾客人群主要是面对着想要购买备用机的小伙伴,而红米K40游戏增强版这款手机则是面对着是vivox60pro和荣耀30pro相比较,该如何选择?如果非要在这两款手机中选择一款手机进行购买,小芳我个人更加倾向于vivox60pro这款手机会更多一些。我给到大家的理由有以下几点,大家不妨参考一下。理由一首先vivox60pro苹果12mini和华为p40之间,选择哪款更好?如果让小芳从这两款手机中选择一款手机进行购买,我个人是更加倾向于华为p40这款手机会更多一些的。不过大家在实际选择手机的过程当中,因为需求是不一样的,那么做出的最终购机选择也是会有
老对手vivo记一功?OPPO挖人意图做第2个华为?联发科表示难受现在的手机芯片依旧掌握在高通手上,得芯者得天下的道理,相信各大厂商都懂。有实力自研芯片的手机厂商在全世界的销量无一不是排名靠前的。这也就使得有一定实力的手机厂商都想要来自研芯片。不设计模式2策略模式做一个商场收银软件,营业员根据客户所购买商品的单价和数量,向客户收费快速地写出代码version1。cppincludeiostreamusingnamespacestdclass设计模式17适配器模式适配器模式将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式主要解决什么问题呢?简单地说,就是需要的设计模式6装饰模式装饰模式是为已有功能动态地添加更多功能的一种方式未使用装饰模式当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为在主类中加入了新的求两个整数的最大公约数,最优算法?求两个整数的最大公约数,要尽量优化算法的性能。暴力枚举法version1includeiostreamincludeusingnamespacestdintGreatestComm设计模式4开放封闭原则开放封闭原则软件实体(类,模块,函数等等),应该可以扩展,但是不可以修改对于扩展是开放的,对于更改是封闭的。我们在做系统的时候,不要指望系统一开始时需求确定,就再也不会变化,既然需美帝养猪?30年扶持三星打败日本半导体,最后仅1天吞掉半个三星要说起三星集团从建立以来,遇到的最大麻烦,应该算是纠缠多年的肥料厂时间,一波三折,亏损了几百亿。而在那之后,三星开始往电子技术行业发展,1973年12月,三星康宁成立1974年7月马斯克又哭了?SpaceX成功发射Model3却出事,网友让车主上天?在5月份的最后一天,马斯克的SpaceX成功发射带领了人类走向了全新的太空时代,而SpaceX发射的重大意义在于探索外太空这件事情,从国家主导变成了商业公司主导,逐步实现着普通人想曾被称为最流氓的软件,如今却是国之栋梁,连腾讯都不敢多说一句华为最近的遭遇相信大家都是有目共睹,上了老美的实体名单的都或多或少有一些影响。但是不得不说,与其说是实体名单,倒不如说是光荣榜。因为无一例外,在里面的都是国内很有实力的,也有很多知DXO成充值榜?同为1亿像素大底,小米10Pro屠榜,motoEdge113?要说起摩托罗拉,相信绝大多数都会想到,自己曾经的那一部摩托罗拉,自从研发出全球第一部手机之后,摩托罗拉就像开挂一样,迅速占领手机市场,半导体业务也是占据全球领先的位置。当然盛极则衰Realme又出最强续航旗舰!号称玩家版,却有1点不符其游戏机设定要说起近年来,国内手机厂商发展最为迅速的,OV两厂必定是赫赫有名,而OPPO的Realme也是在整个发展浪潮中,成为最为亮眼的存在。在Realme上线国内市场一年的时间节点,继续不