grafana接入oauth2
说明
IP | 组件 |
192.168.146.18 | grafana |
192.168.146.19 | nginx(项目运行服务器) |
192.168.208.97 | 本地oauth接入测试服务 |
grafana配置
安装grafana之后,配置文件grafana.ini默认会在/etc/grafana路径下
修改grafana.ini配置
vim grafana.ini
要修改部分
[server]
# Protocol (http, https, h2, socket)
;protocol = http
# The ip address to bind to, empty will bind to all interfaces
;http_addr =
# The http port to use
;http_port = 3000
# The public facing domain name used to access grafana from a browser
;domain = localhost
# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = false
# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
;root_url = %(protocol)s://%(domain)s:%(http_port)s/
root_url = http://192.168.146.18:3000 #grafana访问地址 用于授权回调
[auth.generic_oauth]
enabled = true # 默认是false,改为true。打开oauth认证
name = OAuth
allow_sign_up = true
client_id = some_id #自研平台唯一client_id
client_secret = some_secret #自研平台唯一client_secret
scopes = user:email,read:org
auth_url = http://192.168.208.97:8080/login/oauth/authorize #自研平台授权认证接口
token_url = http://192.168.208.97:8080/login/oauth/token #自研平台生成token接口
api_url = http://192.168.208.97:8080/login/oauth/userinfo #自研平台验证token并返回用户信息
接口开发
注意:这些接口都是grafana静默调用
授权认证接口
请求方式:get
请求路径:/login/oauth/authorize
请求参数
类型 | 名称 | 值 | 描述 |
String | access_type | online | |
String | state | JTlwwAomCy2-H0maDX7JJpzVOCA_-RUfjqlftMoMt7w= | 当前请求唯一密文 |
String | redirect_uri | 配置文件root_url加固定/login/generic_oauth,用于重定向 | |
String | response_type | code | |
String | scope | id email nickname | 配置文件scope |
String | client_id | some_id | 平台唯一client_id |
接口内部实现client_id验证和用户信息查询验证之后将用户id和参数state用做重定向参数
重定向地址:http://192.168.146.18:3000/login/generic_oauth?state={state}&code=xxx
代码示例
@RestController
@Slf4j
@RequestMapping("/login/oauth")
public class AuthApi {
@GetMapping("/authorize")
public void authorize(@RequestParam Map<String, String> params, HttpServletResponse response, HttpServletRequest request) throws IOException {
for (Map.Entry<String, String> entry : params.entrySet()) {
System.out.println(entry.getKey() + "-------------" + entry.getValue());
}
/* 核心业务逻辑 验证client_id 和用户信息 获取用户id*/
String userId = "xxx";
builder.append("state=").append(params.get("state")).append("&code=").append(JWTUtil.createToken(userId, "jwt".getBytes(StandardCharsets.UTF_8)));
String url = "http://192.168.146.18:3000/login/generic_oauth?" + builder.toString();
System.out.println(url);
response.sendRedirect(url);
}
}
生成token接口
请求方式:post
请求路径:/login/oauth/token
请求参数
类型 | 名称 | 值 | 描述 |
String | code | xxx | 授权接口的用户id |
String | grant_type | authorization_code | 固定值 |
String | redirect_uri | 配置文件root_url加固定/login/generic_oauth,用于重定向 |
返回参数
类型 | 名称 | 值 | 描述 |
String | access_token | 认证token | |
String | token_type | Bearer | 验证token会将其添加到token首部 |
String | expiry_in | ||
String | refresh_token |
代码示例
@PostMapping("/token")
public TokenResponse token(TokenParam tokenParam){
System.out.println(tokenParam);
/* 核心业务逻辑 生成token */
String token = xxx;
TokenResponse response = new TokenResponse();
response.setAccess_token(xxx);
response.setToken_type("Bearer");
response.setExpiry_in("1");
response.setRefresh_token("123456");
return response;
}
验证token接口
请求方式:get
请求路径:/login/oauth/userinfo
请求头信息
类型 | 名称 | 值 | 描述 |
String | authorization | Bearer xxx | token_type + access_token |
请求参数:无
返回参数
类型 | 名称 | 值 | 描述 |
String | name | lzz | 用户名 |
String | email | liuzhuzheng@talkweb.com.cn | 用户邮箱 |
代码示例
@GetMapping("/userinfo")
public User userInfo(HttpServletRequest request){
System.out.println(2222);
String authorization = request.getHeader("authorization");
System.out.println(authorization);
/* 核心业务逻辑,验证token并设置用户信息*/
User user = new User();
user.setEmail("liuzhuzheng@talkweb.com.cn");
user.setName("lzz");
return user;
}
测试
访问http://192.168.146.18:3000/login/generic_oauth便可实现用户注册登录grafana
其他代码
TokenParam类
@Data
public class TokenParam {
private String code;
private String grant_type;
private String redirect_uri;
}
TokenResponse类
@Data
public class TokenResponse {
private String access_token;
private String token_type;
private String expiry_in;
private String refresh_token;
}
User类
@Data
public class User {
private String id;
private String email;
private String name;
}
nginx配置代理
如果是将grafana嵌入自己的项目工程中,因为默认grafana设置samesite=lax导致跨域情况下setCookie不能传递,此时需要通过grafana进行代理来实现同域传递
grafana配置文件修改
[server]
;root_url = %(protocol)s://%(domain)s:%(http_port)s/
root_url = http://192.168.146.19/grafana #修改路径
serve_from_sub_path = true #默认为false
nginx配置文件添加
添加grafana相关请求转发
server {
listen 80;
server_name localhost;
location /grafana{
proxy_pass http://192.168.146.18:3000;
proxy_redirect off;
proxy_set_header Host $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;
client_max_body_size 100m;
client_body_buffer_size 256k;
proxy_connect_timeout 500;
proxy_send_timeout 2000;
proxy_read_timeout 2000;
proxy_ignore_client_abort on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
location /login/oauth{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.208.89:8080;
}
location /public{
proxy_pass http://192.168.146.18:3000/public;
}
location /avatar{
proxy_pass http://192.168.146.18:3000/avatar;
}
}
oauth接口修改
授权认证接口中最后需要转发回login/generic_oauth,此时要添加上grafana前缀 如下
@RestController
@Slf4j
@RequestMapping("/login/oauth")
public class AuthApi {
@GetMapping("/authorize")
public void authorize(@RequestParam Map<String, String> params, HttpServletResponse response, HttpServletRequest request) throws IOException {
for (Map.Entry<String, String> entry : params.entrySet()) {
System.out.println(entry.getKey() + "-------------" + entry.getValue());
}
/* 核心业务逻辑 验证client_id 和用户信息 获取用户id*/
String userId = "xxx";
builder.append("state=").append(params.get("state")).append("&code=").append(JWTUtil.createToken(userId, "jwt".getBytes(StandardCharsets.UTF_8)));
/* 需要修改的地方 /login/generic_oauth/ ------> grafana/login/generic_oauth*/
String url = "http://192.168.146.18:3000/grafana/login/generic_oauth?" + builder.toString();
System.out.println(url);
response.sendRedirect(url);
}
}
至此 访问http://192.168.146.19/grafana或者是对应面板的详细地址都能跳转登录页并成功登录。
踩坑点
1、如果是本地测试在windows下安装nginx,可能会导致关不掉,此时可以通过任务管理器关闭
2、如果测试次数过多,可能会导致有多个grafana_session,清除一下当前页面的cookie就行了
3、切记配置grafana配置文件中serve_from_sub_path = true
4、安装的nginx要在当前前端页面部署的服务器上,且监听的是同一个端口,因为端口不同也是跨域