keycloak
docker安装
Details
docker-compose(https://shuze.net/keycloak)
postgres:
container_name: base-postgres
image: registry.cn-shenzhen.aliyuncs.com/shuze/postgres:15.0
volumes:
- /root/postgres/data:/var/lib/postgresql/data
ports:
- "8026:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: "password"
POSTGRES_DB: postgres
keycloak:
image: registry.cn-shenzhen.aliyuncs.com/shuze/keycloak:24.0.2
container_name: base-keycloak
restart: unless-stopped
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://shuze.net:8026/ShuzeKeycloak
KC_DB_USERNAME: postgres
KC_DB_PASSWORD: password
KC_HOSTNAME_URL: https://shuze.net/keycloak
KC_HOSTNAME_ADMIN_URL: https://shuze.net/keycloak
KC_PROXY: edge
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: password
KC_HTTPS_CERTIFICATE_FILE: /etc/x509/https/shuze.net.crt.pem
KC_HTTPS_CERTIFICATE_KEY_FILE: /etc/x509/https/shuze.net.key.pem
entrypoint: /opt/keycloak/bin/kc.sh start
volumes:
- /root/nginx/cert:/etc/x509/https
ports:
- 8443:8443
depends_on:
- postgresnginx
server {
listen 80;
location /keycloak/ {
return 301 https://$host$request_uri;
}
}
server {
location /keycloak/ {
# proxy_pass http://keycloak/; #出错,原因不明
proxy_pass https://120.79.58.102:8443/;
add_header Access-Control-Allow-Headers "requestverificationtoken";#增加预检头
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}abp 设置
1、audience 是受众,指的是 realm,应为 master-realm,account 也可以,解码 tocken 时,。
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
//options.Audience = "WaterSupervision";//openid
options.Audience = "account"; //keycloak———————或为"realm"——————————
});2、Authority,要有证书(如果自发证书,则需安装根证书到本地),否则访问会失败。
"AuthServer": {
"Authority": "https://auth.shuze.net/realms/master",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "ShuzeSwagger",
"SwaggerClientSecret": "PrqSLkrG8NjXm74ZQLeSaSM76HuSj26q"
},3、Swagger 访问成功,需配置参数,
context.Services.AddAbpSwaggerGenWithOAuth中,有两个默认参数需修改
"/protocol/openid-connect/auth", "/protocol/openid-connect/token"4、可能问题
跨域问题-Access to fetch at 'https://auth.shuze.net/realms/master/protocol/openid-connect/token' from origin '' has been blocked by CORS policy: Request header field requestverificationtoken is not allowed by Access-Control-Allow-Headers in preflight response.
产生原因为是进行跨域请求时,浏览器发送了一个预检请求(preflight request),并且目标服务器返回的响应中没有包含 'requestverificationtoken' 这个请求头,因此浏览器拒绝了这个请求。
解决方法:方法一:nginx 中增加 add_header Access-Control-Allow-Headers "requestverificationtoken";即可(推荐)
方法二:删掉 cookie 中的 XSRF-TOKEN。
502 问题:Failed to load resource: the server responded with a status of 502 (Bad Gateway)
??
keycloak设置
客户端Clients需设置两处参数
Web origins http://localhost:8011
Valid redirect URIs http://localhost:8011/*客户端Scopes需包含该服务
postman 取token
1、api Module 中 audience 要对应 realm 或 account
//options.Audience = "WaterSupervision";//openid
options.Audience = "account"; //keycloak———————或为master-realm2、keycloak 获取 Token 主要有两种方式,
一是用户账号(账号+密码),二是 Service Account(clientid+secret)。不同之处在于 Service Account 使用 client secret 登录,登录后只会生成 access token 不会生成 refresh token。 因为每个 keycloak 的 client 只能有一个 Service Account,所以 Service Account 有专门的角色分配 UI 来配置它的权限。
采用 Service Account 调用 api 出现 403 错误,需在 Service accounts roles 中增加 role。
采用授权码可以成功
采用 account 中 password 也可以成功
postman,采用
https://auth.shuze.net/realms/master/protocol/openid-connect/token
client_credentials模式,Content-Type :application/x-www-form-urlencoded
grant_type:client_credentials
client_id:EShopOnAbp_AdministrationService
client_secret:1q2w3e*
scope:IdentityServiceclient_id : <my-client-name>
grant_type : refresh_token
refresh_token: <my-refresh-token>3、postman 访问,ok。采用 x-www-form-urlencoded 模式,需输入以下参数。客户 id 要包含程序的 scope,api 访问地址中设置的 Authority 要采取同一个。
https://auth.shuze.net/realms/master/protocol/openid-connect/token
grant_type:password
username:
password:
client_id:shuzeclient
"scope": "profile email DemoService WaterSupervision",授权码验证
https://auth.shuze.net/realms/master/protocol/openid-connect/auth?client_id=ShuzeSwagger&response_type=code&state=123&redirect_uri=https://localhost:8005/*&scope=openid
client_id:ShuzeSwagger
response_type:code
state:123
redirect_uri:https://localhost:8005/*
scope:openid将带参数的连接贴至浏览器,会要你输入用户名及密码,或直接返回一个连接,从连接中拿到 code
post:https://auth.shuze.net/realms/master/protocol/openid-connect/token
grant_type:authorization_code
client_id:ShuzeSwagger
client_secret:PrqSLkrG8NjXm74ZQLeSaSM76HuSj26q
code:***
redirect_uri:https://localhost:8005/*
scope:openid profile拿 code 要快,就可取得 token
vue-keycloak.js
这里的 on-load 的参数有两个,一个是 login-required,另一个是 check-sso。login-required 会检查你是否登录到了 keycloak 以及判断你登录的客户端是否正确,如果没有登录就跳转到 keycloak 的登录页面;check-sso 只会判断你登录的客户端是否正确,如果没有登录就会保持未登录的状态。
idp(第三方登录)
要让乙系统(使用 OpenIddict 进行权限管理)中的用户访问甲计算平台的 API(使用 Keycloak 进行权限管理)
通过账号+密码的形式来验证您的身份。当您使用支付宝账号登录优酷,这个场景中支付宝即为 IdP。 在 keycloak 中使用 idp 的方式要让乙系统(使用 OpenIddict 进行权限管理)中的用户账号+密码登录甲计算平台(使用 Keycloak 进行权限管理)
甲系统(keycloak 进行权限管理)要开放给乙系统(openiddict 进行权限管理)第三方登录
github 登录
1、到 github 中,Settings/Developer Settings/OAuth Apps/,新建一个 app,会生成 clientid 及 secret,(填入 keycloak idp 中),填写 Authorization callback URL(即为 keycloak 中的 Redirect URI)。
2、keycloak 中,点 idp,选 github,会自动生成 Redirect URI :https://shuze.net/keycloak/realms/DemoTest/broker/github/endpoint,该地址需在github中填写。
3、填写 Client ID 及 Client Secret,从 github 中来。
Keycloak OpenID Connect(keycloak B 访问 keycloak A)
1、在 keycloak A 中增加 idp,类型为 Keycloak OpenID Connect,填写 Alias 名为 keycloak-oidc,会自动生成重定向地址。
2、keycloak A 中,填写 Discovery endpoint,为 keycloak B 权限的发现端点,***/.well-known/openid-configuration,会自动填写相关地址。
3、keycloak A 中,填写 Client ID 及 Client Secret,从 keycloak B 中来。
4、在 keycloak B 中,新建一个 client,选Client authentication,Service accounts roles,设置 secret。在Valid redirect URIs中填入 keycloak A 的重定向地址。
alipay
https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=2021004164640688&scope=auth_user&redirect_uri=
https://shuze.net/keycloak/realms/shuze/broker/alipay/endpoint&state=init功能
abc
Scope 对应 openid 里的 OpenIddictScopes
clientId 对应 openid 里的 OpenIddictApplications
1、身份代理 - 使用外部 OpenID Connect 或 SAML 身份提供商进行身份验证。
2、用于集中管理用户、角色、角色映射、客户端和配置的管理控制台
3、完整登录流程 - 可选的用户自注册、恢复密码、验证电子邮件、要求密码更新等。
4、令牌映射 - 将用户属性、角色等映射到令牌和语句中。
5、客户端适配器。
核心概念
authentication 识别和验证用户的过程。证明“你说的这个你就是你”。 authorization 授予用户访问权限的过程。标明“你可以干什么、不可以干什么”。 credentials 证明用户身份的凭证。可能是密码、一次性密码、数字证书以及指纹。 roles 角色是 RBAC 的重要概念,用于表明用户的身份类型。 user role mapping 用户角色映射关系。通常一个用户可能有多个角色,一个角色也可以对应不同的人。 composite roles 复合角色,听起来很玄乎,其实就是角色的从属关系或者说继承关系。 B 角色从属于 A 角色,那么你拥有了 A 角色就一定拥有 B 角色的权限。 groups 用户组,你可以将一系列的角色赋予定义好的用户组,一旦某用户属于该用户组,那么该用户将获得对应组的所有角色权限。 clients 客户端。通常指一些需要向 keycloak 请求以认证一个用户的应用或者服务,甚至可以说寻求 keycloak 保护并在 keycloak 上注册的请求实体都是客户端。 client adapters keycloak 为了支持多语言和跨平台而设计的适配器,比如适配 Java 的、适配 Python 的。有些是内置的实现,有些需要我们按照 keycloak 的抽象定义来实现。后续我们主要和 Spring Boot Adapter 打交道。 identity provider 用来认证用户的服务,简称 IDP。keycloak 本身就是一个 IDP。这个类似 Spring Security 中的 AuthenticationProvider 接口。
OIDC 客户端类型。
- confidential:机密访问类型用于服务端客户端(需要执行浏览器登录和需要客户端密码)。这个类型用于服务端应用程序。
- public:Public 访问类型是客户端类型客户端(需要执行浏览器登录)。客户端类型应用程序没有安全保存秘密的方式。相反,通过为客户端配置正确的重定向 URI 来限制访问非常重要。
- bearer-only:Bearer-only 访问类型意味着应用程序仅允许 bearer 令牌请求。如果打开这个,应用程序不能参与浏览器登录
public: 适用于客户端应用,如前端 web 系统,包括采用 vue、react 实现的前端项目等。不需要秘钥访问。 confidential: 适用于服务端应用,比如需要浏览器登录以及需要通过密钥获取 access token 的 web 系统。需要秘钥访问。 bearer-only: 适用于服务端应用,只允许使用 bearer token 请接口,项目里的权限是针对接口做校验,请求没有带上 token 就会返回 401。需要秘钥访问。
Standard Flow Enabled 如果打开这个,客户端将使用 OIDC 授权码工作流。
Implicit Flow Enabled 如果打开这个,客户端将使用 OIDC 隐式工作流。
Direct Access Grants Enabled 如果打开这个,客户端将使用 OIDC 直接访问授权。
OAuth 2.0 Device Authorization Grant Enabled 如果打开这个,客户端将使用 OIDC 设备授权许可。
OpenID Connect Client Initiated Backchannel Authentication Grant Enabled
Keycloak 角色
如果打开这个,客户端将使用 OIDC 客户端初始化后端渠道认证许可。
一个 Realm 有多个客户端,一个客户端有多个用户。在 Keycloak 有 3 种角色:
Realm Role:全局角色,属于指定 realm。任何客户端都可以访问这个角色,并且把这个角色映射到任何用户。
Client Role:属于指定客户端的角色。只能映射到该客户端下的用户。
Composite Role:多个角色的组合。
Default Client Scopes 里面的 Scope 不需要在使用 keycloak API 时提供,返回 JSON 中默认会携带。Optional Client Scopes 需要主动添加 scope,需要申请多个则用" "英文空格隔开。
关于访问令牌(access_token)的有效期 访问令牌(access_token)的有效期(expires_in)一般情况下是由访问令牌生命周期(Access Token Lifespan)决定的。但是如果用户会话最长时间(SSO Session Max)小于访问令牌生命周期(Access Token Lifespan),有效期将使用用户会话最长时间(SSO Session Max)的配置。 通常情况下,用户会话最长时间(SSO Session Max)会远远大于访问令牌生命周期(Access_Token_Lifespan)。在用户会话周期内,访问令牌(access_token)临过期时,可以使用刷新令牌(refresh_token)来获取新的访问令牌(access_token)。 关于刷新令牌(refresh_token)的有效期 刷新令牌(refresh token)的有效期(refresh_expires_in)是由用户会话空闲超时(SSO Session Idle)和客户端用户会话空闲超时(Client SSO Session Idle)决定的,有效期取决于两个配置项的较小值。但是如果用户会话最长时间(SSO Session Max)小于用户会话空闲超时(SSO Session Idle)和客户端用户会话空闲超时(Client SSO Session Idle),有效期将使用用户会话最长时间(SSO Session Max)的配置。
Token Exchange
标准令牌交换:版本 2 (V2) - 此功能是完全支持的令牌交换实现,在 Keycloak 服务器启动后默认启用。经测试,只能客户端用户,不能模拟具体用户,原计划在微信小程序中采用,获取token,未成功。
旧版令牌交换:版本 1 (V1) - 此预览功能在 Keycloak 服务器启动后默认不启用。要启用,请使用 --features=preview 或 --features=token-exchange 启动服务器。要使用超出 内部令牌到内部令牌交换 流程的功能,还要启用 admin-fine-grained-authz 功能。
Keycloak 的令牌交换功能如下
客户端可以交换为特定客户端创建的现有 Keycloak 令牌,以获取同一 realm 中针对不同客户端的新令牌。
客户端可以将现有的 Keycloak 令牌交换为外部令牌,例如链接的 Facebook 帐户。
客户端可以将外部令牌交换为 Keycloak 令牌。
客户端可以模拟用户。
标准令牌交换仅支持用例 (1)。旧版令牌交换支持所有四个用例,但它是一个预览功能。
reaml
新建 reaml-demo,新建用户 demoadmin,map admin-role 权限,配置 admin-role 权限,associated roles 增加 filter by clients 中的权限,配置后才有 admin 权限。
keycloak 问题及处理
杂记 | Linux 服务器使用 docker 安装 keycloak(docker-compose)-CSDN 博客
docker run -p 8070:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:23.0.0 start-dev
8443 是生产模型,start
8080 是开发模型,start-dev
手动创建一个数据库 keycloak,字符集 uft8mb4,排序规则 uft8mb4_general_ci
nginx 中要配置 https 8080 ssl
8.134.188.22:8443/realms/demo/.well-known/openid-configuration
keyclaok~web 安全防护 - 张占岭 - 博客园 (cnblogs.com)
你的网站添加了 X-Frame-Options 之后,保存了自己的网站不被其它网站引用,比如其它网站想 iframe 你的网站,通过 X-Frame-Options DENY 之后,其它网站是不容许 iframe 你的网站的。微信扫码采用 iframe 的方式,ALLOW-FROM?
SAMEORIGIN 的协议头,浏览器会在 frame 中只加载同源请求的的资源;如果协议头设置为 ,浏览器会在加载 frame 时屏蔽所有资源,无论请求来自于哪个站点;如果希望开放给某个域名,可以使用 ALLOW-FROM uri 来实现它,DENY 表示拒绝所有请求。https://www.rfc-editor.org/rfc/rfc7034。如果在kc中配置了它,并且在其它网站想通过iframe嵌入KC的页面,那么,如果使用SAMEORIGIN 它会出现如下图提示;如果是同源网站,是可以通过 iframe 访问它的。
你的网站需要引用外部资源,如你需要引用微信的 js 脚本,或者需要 iframe 微信的页面,这时,你需要配置自己网站的 CSP,将微信添加到白名单即可,例如:frame-src 'self' https://www.recaptcha.net https://open.weixin.qq.com "网页安全政策"(Content Security Policy,缩写 CSP)CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。
2、测试端口 ssl
openssl s_client -connect 8.134.188.22:8443微信对接



- 服务器管理指南
- 第 9 章 集成身份提供程序