Spring Boot Admin是用于管理和监控 Spring Boot 应用程序的开源项目。
但是想要把它集成到现有的后台不是很方便,SBA是一个独立的应用,如果想要在后台访问需要开放端口,并且想要查看更多的监控指标需要开放 /actuator/** 接口, SBA默认不需要登录,可以选择集成spring security添加登录验证,但是我想要的是直接在后台查看,而不是跳转后再次登录。
总结下来两个问题:
1、怎么样和现有后台集成
2、接入现有安全认证体系
(其实就是一个问题,怎么集成到现有后台,就好像打开一个新菜单页面,并且只有登录后才能访问)
1、反向代理
第一个问题我想到了反向代理,使用反向代理屏蔽SBA的地址,只要你不在nginx配置,其他人就无法访问SBA的默认页面
反向代理我使用了smiley-http-proxy-servlet这个开源框架,当然也有其他框架可以使用,比如Charon
这里我用smiley-http-proxy-servlet举个例子
首先引入依赖
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.12.1</version>
</dependency>
配置代理
import org.mitre.dsmiley.httpproxy.ProxyServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServlet;
/**
* @author sushengbuyu
* @date 2022/8/2
*/
@Configuration
public class SpringBootAdminProxy {
@Bean
public ServletRegistrationBean<HttpServlet> servletRegistrationBean() {
ServletRegistrationBean<HttpServlet> servletRegistrationBean = new ServletRegistrationBean<>(new ProxyServlet()
, "/boot-admin/*");
servletRegistrationBean.addInitParameter(ProxyServlet.P_TARGET_URI, "http://localhost:9000/boot-admin/");
servletRegistrationBean.addInitParameter(ProxyServlet.P_LOG, "true");
return servletRegistrationBean;
}
}
SBA配置
server:
port: 9000
spring:
main:
allow-bean-definition-overriding: true
boot:
admin:
context-path: /boot-admin
ui:
# 本地代理地址
public-url: http://localhost:8003/boot-admin/
后台页面配置
<template>
<div v-loading="loading" :style="'height:'+ height">
<iframe id="boot-admin" :src="url" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" />
</div>
</template>
<script>
import { getToken } from '@/utils/auth'
export default {
name: 'BootAdmin',
data() {
return {
height: document.documentElement.clientHeight - 94.5 + 'px;',
loading: true,
url: 'http://localhost:8003/boot-admin',
html: ''
}
},
created: function() {
// 拼接token
this.url = this.url + '?Authorization=' + getToken()
},
mounted: function() {
setTimeout(() => {
this.loading = false
}, 100)
const that = this
window.onresize = function temp() {
that.height = document.documentElement.clientHeight - 94.5 + 'px;'
}
}
}
</script>
访问效果
就像访问一个普通菜单一样
2、token传递,SBA添加Authorization请求头
后台页面代理里在访问SBA页面时携带了当前登录用户的token令牌,这个就是用来认证/actuator接口的
SBA需要接收令牌并且在访问 /actuator接口时 添加Authorization请求头,放入token令牌
首先,接收并存储令牌
import de.codecentric.boot.admin.server.web.client.CompositeHttpHeadersProvider;
import de.codecentric.boot.admin.server.web.client.HttpHeadersProvider;
import de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunction;
import de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunctions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
/**
* @author sushengbuyu
* @date 2022/8/2
*/
@Slf4j
@Component
public class AdminFilter implements Filter, Ordered {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String uri = request.getRequestURI();
if ("/boot-admin/".equals(uri)) {
log.info("URL: {}, Authorization: {}", uri, request.getParameter("Authorization"));
AuthHttpHeadersProvider.AUTH = request.getParameter("Authorization");
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Bean
@Order(0)
public InstanceExchangeFilterFunction addHeadersInstanceExchangeFilter(
List<HttpHeadersProvider> headersProviders) {
headersProviders.add(new AuthHttpHeadersProvider());
return InstanceExchangeFilterFunctions.addHeaders(new CompositeHttpHeadersProvider(headersProviders));
}
@Override
public int getOrder() {
return 0;
}
}
添加自定义过滤器,拦截 /boot-admin/ 请求,获取token令牌并保存至静态变量 (这里有个问题,token只能存一个,后续待完善)
SBA添加请求头
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.web.client.HttpHeadersProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
/**
* 添加自定义请求头
* @author sushengbuyu
* @date 2022/8/2
*/
@Slf4j
public class AuthHttpHeadersProvider implements HttpHeadersProvider {
public static String AUTH = "";
@Override
public HttpHeaders getHeaders(Instance instance) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", AUTH);
return headers;
}
}
实现SBA的HttpHeadersProvider接口,添加Authorization请求头
后台的 /actuator 接口现在可以不用放开了,SBA请求时会携带用户token过来,直接验证即可
后台登录用户访问
未登录用户访问