首页 文章 精选 留言 我的

精选列表

搜索[java],共10000篇文章
优秀的个人博客,低调大师

java版spring cloud 多租户社交电子商务平台-Spring Cloud Security

一、SpringCloud Security简介 Spring Cloud Security提供了一组原语,用于构建安全的应用程序和服务,而且操作简便。可以在外部(或集中)进行大量配置的声明性模型有助于实现大型协作的远程组件系统,通常具有中央身份管理服务。它也非常易于在Cloud Foundry等服务平台中使用。在Spring Boot和Spring Security OAuth2的基础上,可以快速创建实现常见模式的系统,如单点登录,令牌中继和令牌交换。 功能: 从Zuul代理中的前端到后端服务中继SSO令牌 资源服务器之间的中继令牌 使Feign客户端表现得像OAuth2RestTemplate(获取令牌等)的拦截器 在Zuul代理中配置下游身份验证 二、SpringCloud Security知识点 封装顺序是这样的:spring security及其各个模块=》spring cloud security=》spring boot autoconfigure的security部分,比如autoconfigure模块有个spring security的sso,是对spring security在oath2下的封装,spring oauth2 authorizeserver,resourceserver,认证服务器和资源服务器是怎么交互的,token_key,/oauth/token/ refresh/token,resourceserver就是业务系统,oauth client 就是边缘业务系统,比如直接面向用户的UI系统,或者UI系统直接调用的API接口这一层; JWT和OAuth2的区别?看到好多人在比较这两个东西,现在终结这个问题:JWT只是OAuth2中的token的一种类型。 jwt client(Resource Server或者Zuul等),使用jwt的业务系统在解码acces_token的时候,需要一个toke_key,这个token-key就是JWT Client应用启动的时候从Auth Server拉取的,接口是token/token_key单点登录这种功能,好多javaee容器都自带的,像webspherespring Security完全将认证和授权分开了,资源只需要声明自己是需要认证的,需要什么样的权限,只管跟当前用户要access_token。授权的四种方式任意,只要拿到token就可以去让资源去认证。 边缘服务器需要开启@EnableOAuth2Sso,但是边缘服务器也是一个ResourceServer,边缘服务器如果是zuul的话,就不是一个ResourceServer了,只需要添加@EnableOAuth2Sso注解就可以了; client_credentials模式下spring boot不会帮助spring Security构建ClientCredentialsResourceDetails 对象,需要开发者自己创建 favicon.icon,记得把这个东西过滤掉 在其中一个边缘服务上,您可能需要启用单点登录。 @EnableOAuthSso,只需要在边缘服务器指定没用来引导未登录的用户登录系统。@EnableOAuthSso将允许您将未经认证的用户的自动重定向转向授权服务器,他们将能够登录 EnableOAuth2Client,在中间中继的时候用ClientCredentialsTokenEndpointFilter,AS设置了allowFormAuthenticationForClients才会有,详情看这里面的AuthorizationServerSecurityConfigurer#configure(HttpSecurity http)逻辑,这点非常重要,ClientCredentialsTokenEndpointFilter是用来验证clientid和client_secret的,使用clientid和client_secret换取下一步的东西; TokenGranter,AuthorizationCodeTokenGranter,ClientCredentialsTokenGranter,RefreshTokenGranter,ImplicitTokenGranter,ResourceOwnerPasswordTokenGranter TokenServices分为两类,一个是用在AuthenticationServer端,AuthorizationServerTokenServices,ResourceServer端有自己的tokenServices接口, BearerTokenExtractor,从其可以看出,token的获取顺序,Header,parameters(get/post) spring security 保护自己的配置,作为ResourceServer的权限配置和作为AuthorizationServer的配置都是在不同的地方 An OAuth 2 authentication token can contain two authentications: one for the client(OAuth2 Client) and one for the user. Since some OAuth authorization grants don’t require user authentication, the user authentication may be null. jwt是不需要存储access_toen的,jwt的机制就是将所有的信息都存在了token里面,从JwtTokenStore也可以看出来 OAuth2AuthenticationManager是密切与token认证相关的,而不是与获取token密切相关的。这是真正认证的地方,一会重点debug,resourceIds每一个ResourceServer在配置的时候,ResourceServerConfiguration,需要配置一个resourceID,一个ResourceServer只能配置一个oauth/token = 先验证的是clientid和clientsecret,接着在验证username和userpassword,都是用的ProvideManager,两次验证是两个不同的请求,oauth2客户端会使用RestTemplate请求服务器的接口ClientCredentialsTokenEndpointFilter用来验证clientId和clientsecret的: OAuth2ClientAuthenticationProcessingFilter:OAuth2客户端用来从OAuth2认证服务器获取access token,也可以从OAuth2认证服务器加载authentication对象到OAuth2客户端的SecurityContext对象中;里面调用OAuth2AuthenticationManager#authenticate()方法使用DefaultTokenServices ,DefaultTokenServices 使用JwtTokenStore,JwtTokenStore使用JwtAccessTokenConverter来将JWT解密成Auth对象。 来从AuthServer请求授权信息accessToken被解密成如下的JWT对象:{“alg”:”RS256”,”typ”:”JWT”} {“exp”:1503758022,”user_name”:”admin”,”authorities”:[“ROLE_TRUSTED_CLIENT”,”ROLE_ADMIN”,”ROLE_USER”],”jti”:”d56f43d2-6c4a-46cf-85f3-050ee195a2bd”,”client_id”:”confidential”,”scope”:[“read”]} [128 crypto bytes]AbstractSecurityInterceptor#befroeInvaction 是ResourceServer获取认证信息的地方只要是需要验证token有效性的都需要jwt.key-uri的配置 AffirmativeBased值得debugTIPS @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/favicon.ico"); } @Bean @Override protected UserDetailsService userDetailsService(){ InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("user").password("password").roles("USER").authorities("USER").build()); manager.createUser(User.withUsername("admin").password("password").roles("USER", "ADMIN", "TRUSTED_CLIENT").authorities("USER").build()); return manager; } 这两种方式有差别,牵扯到UsernamePasswordAuthenticationFilter和ClientCredentialsTokenEndpointFilter security: oauth2: client: client-id: confidential client-secret: secret access-token-uri: http://localhost:8080/oauth/token user-authorization-uri: http://localhost:8080/oauth/authorize use-current-uri: true resource: jwt: key-uri: http://localhost:8080/oauth/token_key filter-order: 3

优秀的个人博客,低调大师

突破Java面试(23-4) - 再深入Redis Replication的完整执行流程及原理

0 Github 1 复制的完整流程 slave node启动,仅仅保存master node的信息,包括master node的host和ip,但复制流程尚未开始master host和ip配置在 redis.conf 中的 slaveof slave node内部有个定时任务,每s 检查是否有新的master node要连接和复制,若发现,就跟master node建立socket网络连接 slave node发送ping命令给master node 口令认证 - 若master设置了requirepass,那么salve node必须同时发送masterauth的口令认证 master node第一次执行全量复制,将所有数据发给slave node master node后续持续将写命令,异步复制给slave node 完整复制的基本流程图

优秀的个人博客,低调大师

Java开发中存在这样的代码,反而影响整体整洁和可读性

不完美的库类 不完美的库类(Incomplete Library Class) 当一个类库已经不能满足实际需要时,你就不得不改变这个库(如果这个库是只读的,那就没辙了)。 问题原因 许多编程技术都建立在库类的基础上。库类的作者没用未卜先知的能力,不能因此责怪他们。麻烦的是库往往构造的不够好,而且往往不可能让我们修改其中的类以满足我们的需要。 解决方法 如果你只想修改类库的一两个函数,可以运用引入外加函数(Introduce Foreign Method); 如果想要添加一大堆额外行为,就得运用引入本地扩展(Introduce Local Extension)。 收益 减少代码重复(你不用一言不合就自己动手实现一个库的全部功能,代价太高) 何时忽略 如果扩展库会带来额外的工作量。 重构方法说明 引入外加函数(Introduce Foreign Method) 问题 你需要为提供服务的类增加一个函数,但你无法修改这个类。 class Report { //... void sendReport() { Date nextDay = new Date(previousEnd.getYear(), previousEnd.getMonth(), previousEnd.getDate() + 1); //... } } 解决 在客户类中建立一个函数,并一个第一个参数形式传入一个服务类实例。 class Report { //... void sendReport() { Date newStart = nextDay(previousEnd); //... } private static Date nextDay(Date arg) { return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1); } } 引入本地扩展(Introduce Local Extension) 问题 你需要为服务类提供一些额外函数,但你无法修改这个类。 解决 建立一个新类,使它包含这些额外函数,让这个扩展品成为源类的子类或包装类。 中间人 中间人(Middle Man) 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节。封装往往伴随委托。但是人们可能过度运用委托。比如,你也许会看到一个类的大部分有用工作都委托给了其他类,类本身成了一个空壳,除了委托之外不做任何事情。 解决方法 应该运用移除中间人(Remove Middle Man),直接和真正负责的对象打交道。 收益 减少笨重的代码。 何时忽略 如果是以下情况,不要删除已创建的中间人: 添加中间人是为了避免类之间依赖关系。 一些设计模式有目的地创建中间人(例如代理模式和装饰器模式)。 重构方法说明 移除中间人(Remove Middle Man) 问题 某个类做了过多的简单委托动作。 解决 让客户直接调用委托类。 依恋情结 依恋情结(Feature Envy) 一个函数访问其它对象的数据比访问自己的数据更多。 问题原因 这种气味可能发生在字段移动到数据类之后。如果是这种情况,你可能想将数据类的操作移动到这个类中。 解决方法 As a basic rule, if things change at the same time, you should keep them in the same place. Usually data and functions that use this data are changed together (although exceptions are possible). 有一个基本原则:同时会发生改变的事情应该被放在同一个地方。通常,数据和使用这些数据的函数是一起改变的。 如果一个函数明显应该被移到另一个地方,可运用搬移函数(Move Method)。 如果仅仅是函数的部分代码访问另一个对象的数据,运用提炼函数(Extract Method)将这部分代码移到独立的函数中。 如果一个方法使用来自其他几个类的函数,首先确定哪个类包含大多数使用的数据。然后,将该方法与其他数据一起放在此类中。或者,使用提炼函数(Extract Method)将方法拆分为几个部分,可以放置在不同类中的不同位置。 收益 减少重复代码(如果数据处理的代码放在中心位置)。 更好的代码组织性(处理数据的函数靠近实际数据)。 何时忽略 有时,行为被有意地与保存数据的类分开。这通常的优点是能够动态地改变行为(见策略设计模式,访问者设计模式和其他模式)。 重构方法说明 搬移函数(Move Method) 问题 你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。 解决 在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是旧函数完全移除。 提炼函数(Extract Method) 问题 你有一段代码可以组织在一起。 void printOwing() { printBanner(); //print details System.out.println("name: " + name); System.out.println("amount: " + getOutstanding()); } 解决 移动这段代码到一个新的函数中,使用函数的调用来替代老代码。 void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails(double outstanding) { System.out.println("name: " + name); System.out.println("amount: " + outstanding); } 狎昵关系 狎昵关系(Inappropriate Intimacy) 一个类大量使用另一个类的内部字段和方法。 问题原因 类和类之间应该尽量少的感知彼此(减少耦合)。这样的类更容易维护和复用。 解决方法 最简单的解决方法是运用搬移函数(Move Method)和搬移字段(Move Field)来让类之间斩断羁绊。 你也可以看看是否能运用将双向关联改为单向关联(Change Bidirectional Association to Unidirectional)让其中一个类对另一个说分手。 如果这两个类实在是情比金坚,难分难舍,可以运用提炼类(Extract Class)把二者共同点提炼到一个新类中,让它们产生爱的结晶。或者,可以尝试运用隐藏委托关系(Hide Delegate)让另一个类来为它们牵线搭桥。 继承往往造成类之间过分紧密,因为子类对超类的了解总是超过后者的主观愿望,如果你觉得该让这个子类自己闯荡,请运用以委托取代继承(Replace Inheritance with Delegation)来让超类和子类分家。 收益 提高代码组织性。 提高代码复用性。 重构方法说明 搬移函数(Move Method) 问题 你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。 解决 在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是旧函数完全移除。 搬移字段(Move Field) 问题 在你的程序中,某个字段被其所驻类之外的另一个类更多地用到。 解决 在目标类新建一个字段,修改源字段的所有用户,令他们改用新字段。 将双向关联改为单向关联(Change Bidirectional Association to Unidirectional) 问题 两个类之间有双向关联,但其中一个类如今不再需要另一个类的特性。 解决 去除不必要的关联。 提炼类(Extract Class) 问题 某个类做了不止一件事。 解决 建立一个新类,将相关的字段和函数从旧类搬移到新类。 隐藏委托关系(Hide Delegate) 问题 客户通过一个委托类来调用另一个对象。 解决 在服务类上建立客户所需的所有函数,用以隐藏委托关系。 以委托取代继承(Replace Inheritance with Delegation) 问题 某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。 解决 在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉两者之间的继承关系。 过度耦合的消息链 过度耦合的消息链(Message Chains) 消息链的形式类似于:obj.getA().getB().getC()。 问题原因 如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象……这就是消息链。实际代码中你看到的可能是一长串 getThis()或一长串临时变量。采取这种方式,意味客户代码将与查找过程中的导航紧密耦合。一旦对象间关系发生任何变化,客户端就不得不做出相应的修改。 解决方法 可以运用隐藏委托关系(Hide Delegate)删除一个消息链。 有时更好的选择是:先观察消息链最终得到的对象是用来干什么的。看看能否以提炼函数(Extract Method)把使用该对象的代码提炼到一个独立函数中,再运用搬移函数(Move Method)把这个函数推入消息链。 收益 能减少链中类之间的依赖。 能减少代码量。 何时忽略 过于侵略性的委托可能会使程序员难以理解功能是如何触发的。 重构方法说明 隐藏委托关系(Hide Delegate) 问题 客户通过一个委托类来调用另一个对象。 解决 在服务类上建立客户所需的所有函数,用以隐藏委托关系。 提炼函数(Extract Method) 问题 你有一段代码可以组织在一起。 void printOwing() { printBanner(); //print details System.out.println("name: " + name); System.out.println("amount: " + getOutstanding()); } 解决 移动这段代码到一个新的函数中,使用函数的调用来替代老代码。 void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails(double outstanding) { System.out.println("name: " + name); System.out.println("amount: " + outstanding); } 搬移函数(Move Method) 问题 你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。 解决 在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是旧函数完全移除。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册