这是我见过最强的单点登录认证系统!

项目介绍

MaxKey 单点登录认证系统,谐音马克思的钥匙寓意是最大钥匙,支持 OAuth 2.x/OpenID Connect、SAML 2.0、JWT、CAS、SCIM 等标准协议,提供简单、标准、安全和开放的用户身份管理(IDM)、身份认证(AM)、单点登录(SSO)、RBAC 权限管理和资源管理等。

单点登录(Single Sign On)简称为SSO 、用户只需要登录认证中心一次就可以访问所有相互信任的应用系统,无需再次登录,主要功能:

  1. 所有应用系统共享一个身份认证系统
  2. 所有应用系统能够识别和提取 ticket 信息

MaxKey 注重企业级场景下的性能、安全和易用性,广泛应用于医疗、金融、政府和制造等行业。

功能特性

标准认证协议

登录支持

  1. 提供标准的认证接口以便于其他应用集成 SSO,安全的移动接入,安全的 API、第三方认证和互联网认证的整合。
  2. 提供用户生命周期管理,支持 SCIM 2 协议;开箱即用的连接器(Connector)实现身份供给同步。
  3. 简化微软 Active Directory 域控、标准 LDAP 服务器机构和账号管理,密码自助服务重置密码。
  4. IDaas 多租户功能,支持集团下多企业独立管理或企业下不同部门数据隔离的,降低运维成本。
  5. 认证中心具有平台无关性、环境多样性,支持 Web、手机、移动设备等, 如 Apple iOS,Andriod 等,将认证能力从 B/S 到移动应用全面覆盖。
  6. 配置化的密码策略、访问策略;支持 Ip2region 或 GeoLite2 地理库精准 IP 定位 ,强大安全审计,对用户全生命周期审计、访问行为记录追溯审计、安全合规审计、安全风险预警。
  7. 基于 Java EE 平台,微服务架构,采用 Spring、MySQL、Tomcat、Redis、MQ 等开源技术,扩展性强。
  8. 开源、安全、自主可控。

主界面

实时报表

用户管理

应用管理

系统安全性

安全性

二次密码登录

单点登录使用户能在一个入口完成登录后,一般情况下用户在点击应用图标时,直接通过相应的协议,登录到应用系统;但是有时要针对特定的用户、特定的应用进行二次密码校验的功能,防止关键系统的登录,导致的信息敏感泄露,比如财务系统或者个人工资账单,在实际工作中经常出现工作代理的情况,即使出现单点登录的密码泄露,二次密码也很好地保护敏感应用系统;

单点退出

单点退出是指用户在一个系统退出后,其所能单点登录访问的所有系统都同时退出。单点退出主要是为提高安全性,避免用户忘记退出所有应用而造成信息的泄密。其实现方式也非常简单,由于 SSO 和单点登录的应用都是分开的,使用不同的域名,只是通过认证协议帮助用户在多个应用系统中传递身份和登录系统。因此,首先注销单点登录应用,然后修改每个应用系统都使用 MaxKey 的单点退出页面,单点登录的退出页面会将用户登录的 Session 注销掉。

会话超时设计

为节约服务端资源,并基于安全性考虑,对于长时间没有活动的客户端其会话将被自动终结。同时,为保证用户的单点登录不受影响,其所有超时都在 MaxKey 端集中控制,即 MaxKey 的会话超时时间比集成的应用系统会话超时时间略长。例如希望实现用户不活动 30 分钟就终止会话,则将 MaxKey 的不活动超时时间设置成 30 分钟,集成应用的不活动超时时间设置成 40 分钟。如果用户登录后打开多个应用,并一直只访问某个应用,而其他应用长时间没有被访问导致应用会话超时,用户再次点击该已超时的应用时,用户会被应用要求重新登录。为避免这种情况,应用检测到用户会话超时后需将用户重定向到登录页面,MaxKey 此时再次实现单点登录,登录成功后应用可重新将用户定向到期之前访问的 URL 或者该应用的首页。

防暴力破解

由于认证系统需对互联网提供服务,为避免互联网中恶意的暴力破解,系统需提供防暴力破解能力。防暴力破解的关键是提供一种机制,能阻止计算机用穷举法试探用户口令。目前一种广泛使用的防暴力破解技术是 CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart),即在登录界面除用户名+口令之外再增加一个扭曲的数字或字母字段,让用户输入,这种字段人很容易看懂,但是计算机却很难识别,从而避免计算机用穷举法猜测用户密码,这种技术的应用在互联网应用上经常可以看到。

连续登陆次失败策

使用连续多次登录失败即锁定帐号一定时间的设置,例如如果某个帐号连续 6 次登录失败就锁定该帐号两小时,这种方式也可以避免暴力破解。

静态密码策略

对密码进行限制无非是为了强制用户设置一个更加安全的密码,密码策略主要有以下几种:

(1)密码必须符合复杂性要求

(2)密码长度最小值

(3)密码最长使用期限

(4)密码最短使用期限

(5)强制密码历史

(6)使用可还原的加密存储密码

双因素身份认证

双因素身份认证就是通过你所知道再加上你所能拥有的这二个要素组合到一起才能发挥作用的身份认证系统。双因素认证是一种采用时间同步技术的系统,采用了基于时间、事件和密钥三变量而产生的一次性密码来代替传统的静态密码。每个动态密码卡都有一个唯一的密钥,该密钥同时存放在服务器端,每次认证时动态密码卡与服务器分别根据同样的密钥,同样的随机参数(时间、事件)和同样的算法计算了认证的动态密码,从而确保密码的一致性,从而实现了用户的认证。就像我们去银行办卡送的口令牌. 多因素认证(MFA),是一种计算机访问控制的方法,用户要通过两种以上的认证机制之后,才能得到授权,使用计算机资源。MFA 的目的是建立一个多层次的防御,使未经授权的人访问计算机系统或网络更加困难,从而提高安全性。推荐:那几本霸占我休息时间的PDF!

密码存储

基于 Spring Security 实现密码加密和验证,规则是通过对密码明文添加**{noop}**前缀

MaxKey 默认密码加密策略 BCrypt,用户表(userinfo)->密码字段(password),存储方式**{类型}密文**

bcrypt 编码算法

bcrypt 使用的是布鲁斯·施内尔在 1993 年发布的 Blowfish 加密算法。bcrypt 算法将 salt 随机并混入最终加密后的密码,验证时也无需单独提供之前的 salt,从而无需单独处理 salt 问题。加密后的格式一般为:

 

javascript

复制代码

$2a$10$/bTVvqqlH9UiE0ZJZ7N2Me3RIgUCdgMheyTgV0B4cMCSokPa.6oCa

其中:$是分割符,无意义;2abcrypt加密版本号;10cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

bcrypt 特点

bcrypt 有个特点就是非常慢。这大大提高了使用彩虹表进行破解的难度。也就是说该类型的密码暗文拥有让破解者无法忍受的时间成本。同时对于开发者来说也需要注意该时长是否能超出系统忍受范围内。通常是 MD5 的数千倍。同样的密码每次使用 bcrypt 编码,密码暗文都是不一样的。也就是说你有两个网站如果都使用了 bcrypt 它们的暗文是不一样的,这不会因为一个网站泄露密码暗文而使另一个网站也泄露密码暗文。所以从 bcrypt 的特点上来看,其安全强度还是非常有保证的。

不推荐使用 md5

首先 md5 不是加密算法,是哈希摘要。以前通常使用其作为密码哈希来保护密码。由于彩虹表的出现,md5 和 sha1 之类的摘要算法都已经不安全了。如果有不相信的同学 可以到一些解密网站 如 cmd5 网站尝试解密 你会发现 md5 和 sha1 是真的非常容易被破解。

近期被裁,面试找工作,跳槽涨薪,没有面试机会,转行转码等等

可以直接找老师1v1免费职业规划,定制突击路线一次

关注公众号即可:“技术分享官”
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
源码简介与安装说明: MaxKey(马克思的钥匙)用户单点登录认证系统(Sigle Sign On System),寓意是最大钥匙,是业界领先的企业级IAM身份管理和身份认证产品,支持OAuth 2.0/OpenID Connect、SAML 2.0、JWT、CAS等标准化的开放协议,提供简单、标准、安全和开放的用户身份管理(IDM)、身份认证(AM)、单点登录(SSO)、RBAC权限管理和资源管理等。 MaxKey主要功能: 1、所有应用系统共享一个身份认证系统 2、所有应用系统能够识别和提取ticket信息 3、提供标准的认证接口以便于其他应用集成SSO,安全的移动接入,安全的API、第三方认证和互联网认证的整合。 4、提供用户生命周期管理,支持SCIM 2协议,基于Apache Kafka代理,通过连接器(Connector)实现身份供给同步。 5、认证中心具有平台无关性、环境多样性,支持Web、手机、移动设备等, 如Apple iOS,Andriod等,将认证能力从B/S到移动应用全面覆盖。 6、多种认证机制并存,各应用系统可保留原有认证机制,同时集成认证中心的认证;应用具有高度独立性,不依赖认证中心,又可用使用认证中心的认证,实现单点登录。 7、基于Java平台开发,采用Spring、MySQL、Tomcat、Apache Kafka、Redis等开源技术,支持微服务,扩展性强。 8、许可证 Apache License, Version 2.0,开源免费。 源码更新日志: MaxKey单点登录认证系统 更新v2.4.0 动态用户组实现(基于用户属性或机构) 任职机构和兼职机构 登录会话切换的优化 我的应用界面隐藏visible = 0的应用 构建脚本的优化和更新 全新的版本号定义,正式版本jar不再添加 RELEASE 后缀声明,author由shimingxy改为maxkeyTop SAML2.0 SP登录引导的优化 SAML2.0 SP DEMO,案例参 https://github.com/MaxKeyTop/spring-boot-security-saml-sample docker支持的优化 源代码增加LICENSE声明 JWT的分离成protocols下子项目 密码策略提示参数问题修复 SAML 2.0 Metadata优化 HandlerInterceptorAdapter@deprecated 调整为 AsyncHandlerInterceptor mybatis-jpa升级,添加@Entity和@Transient支持,优化update时字段为null的处理,SQL代码优化 README更新及中文和英文支持 认证失败时,authentication 空指针异常 SAML Metadata URL配置读取 添加组和角色时按登录名查询成员 firefox点击验证码无更新修复 官网内容更新 管理MGT样式调整优化 依赖jar引用、更新和升级
以下是一个基于Python的MOPSO算法代码程序,供您参考: ```python import random import math class Particle: def __init__(self, num_dimensions): self.num_dimensions = num_dimensions self.position = [random.uniform(0, 1) for _ in range(num_dimensions)] self.velocity = [random.uniform(0, 1) for _ in range(num_dimensions)] self.best_position = list(self.position) self.best_fitness = float('inf') self.fitness = float('inf') self.crowding_distance = 0 def update_velocity(self, global_best_position, inertia_weight, cognitive_weight, social_weight): for i in range(self.num_dimensions): r1 = random.uniform(0, 1) r2 = random.uniform(0, 1) cognitive_component = cognitive_weight * r1 * (self.best_position[i] - self.position[i]) social_component = social_weight * r2 * (global_best_position[i] - self.position[i]) self.velocity[i] = inertia_weight * self.velocity[i] + cognitive_component + social_component def update_position(self, bounds): for i in range(self.num_dimensions): self.position[i] += self.velocity[i] if self.position[i] > bounds[i][1]: self.position[i] = bounds[i][1] self.velocity[i] = 0 elif self.position[i] < bounds[i][0]: self.position[i] = bounds[i][0] self.velocity[i] = 0 def evaluate_fitness(self, objective_function): self.fitness = objective_function(self.position) if self.fitness < self.best_fitness: self.best_fitness = self.fitness self.best_position = list(self.position) class MOPSO: def __init__(self, objective_function, num_particles, num_iterations, num_dimensions, bounds, inertia_weight, cognitive_weight, social_weight): self.objective_function = objective_function self.num_particles = num_particles self.num_iterations = num_iterations self.num_dimensions = num_dimensions self.bounds = bounds self.inertia_weight = inertia_weight self.cognitive_weight = cognitive_weight self.social_weight = social_weight self.global_best_position = [random.uniform(bounds[i][0], bounds[i][1]) for i in range(num_dimensions)] self.global_best_fitness = float('inf') self.particles = [Particle(num_dimensions) for _ in range(num_particles)] def run(self): for i in range(self.num_iterations): for particle in self.particles: particle.update_velocity(self.global_best_position, self.inertia_weight, self.cognitive_weight, self.social_weight) particle.update_position(self.bounds) particle.evaluate_fitness(self.objective_function) if particle.fitness < self.global_best_fitness: self.global_best_fitness = particle.fitness self.global_best_position = list(particle.position) fronts = self.fast_non_dominated_sort(self.particles) for i, front in enumerate(fronts): self.calculate_crowding_distance(front) self.particles.sort(key=lambda particle: particle.crowding_distance, reverse=True) self.particles = self.particles[:self.num_particles] if len(self.particles) == self.num_particles: break return self.global_best_position, self.global_best_fitness def fast_non_dominated_sort(self, particles): fronts = [] remaining_particles = list(particles) while len(remaining_particles) > 0: front = [] for particle in remaining_particles: particle.domination_count = 0 particle.dominated_particles = [] for other_particle in remaining_particles: if particle == other_particle: continue if self.dominates(particle, other_particle): particle.dominated_particles.append(other_particle) elif self.dominates(other_particle, particle): particle.domination_count += 1 if particle.domination_count == 0: front.append(particle) fronts.append(front) for particle in front: remaining_particles.remove(particle) return fronts def dominates(self, particle1, particle2): for i in range(self.num_dimensions): if particle1.fitness[i] > particle2.fitness[i]: return False return True def calculate_crowding_distance(self, particles): num_particles = len(particles) for particle in particles: particle.crowding_distance = 0 for i in range(self.num_dimensions): particles.sort(key=lambda particle: particle.fitness[i]) particles[0].crowding_distance = float('inf') particles[num_particles - 1].crowding_distance = float('inf') fitness_range = particles[num_particles - 1].fitness[i] - particles[0].fitness[i] for j in range(1, num_particles - 1): distance = particles[j + 1].fitness[i] - particles[j - 1].fitness[i] particles[j].crowding_distance += distance / fitness_range ``` 这段程序是一个基于Python的MOPSO算法实现,包括一个粒子类和一个MOPSO类。程序实现了多目标优化问题的求解,其中使用了快速非支配排序和拥挤距离计算等技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值