spring security小ネタ

こんにちわ、猫好きリーマンのほげPGです。
3つほど小ネタ紹介です。
1, ログインユーザをログ出力する
仕組み:セッションに認証情報が保存されているので、リクエストの入り口で認証情報を取得しMDC.put()するだけ。
フィルター
@Component
@Slf4j
public class HogeLoggingFilter extends CommonsRequestLoggingFilter {
@Override
protected boolean shouldLog(HttpServletRequest request) {
String uri = request.getServletPath();
return !checkStaticPath(uri);
}
private boolean checkStaticPath(String path) {
return path.startsWith("/static/");
}
@Override
protected void beforeRequest(HttpServletRequest request, String message) {
LoginUser user = getLoginUser(request.getSession(false));
if (user != null) {
MDC.put("USER-ID", user.getId());
}
}
public LoginUser getLoginUser(HttpSession session) {
if (session != null) {
SecurityContext securityContext = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
if (securityContext != null) {
Authentication authentication = securityContext.getAuthentication();
return (LoginUser) authentication.getPrincipal();
}
}
return null;
}
@Override
protected void afterRequest(HttpServletRequest request, String message) {
MDC.remove("USER-ID");
}
}
※継承元が用途に合っていないのでjavax.servlet.Filter を使った方が良いかも
ログ定義
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<charset>UTF-8</charset>
<pattern>%date{yyyy-MM-dd HH:mm:ss} %-5level %5.5thread %X{USER-ID} \(%file:%line\) %M - %msg%n</pattern>
</encoder>
</appender>
2, 更新系SQLだけログ出力する
仕組み:mybatis限定になるが、Mapperのメソッド名を更新系はinsert/update/deleteで始まるメソッド名にし、ログフィルターでロガー名から更新系か判断する。
ログフィルター
public class SqlLogFilter extends Filter<ILoggingEvent> {
private static final List<String> DEFAULT_ACCEPT = List.of("insert", "update", "delete");
private static boolean checkName(String name) {
for (String s : DEFAULT_ACCEPT) {
if (name.startsWith(s)) {
return true;
}
}
return false;
}
@Override
public FilterReply decide(ILoggingEvent event) {
String loggerName = event.getLoggerName();
if (loggerName.startsWith("jp.co.ois.hoge.springsecurity.mapper")) {
int ix = loggerName.lastIndexOf(".");
String name = loggerName.substring(ix + 1);
if (!checkName(name)) {
return FilterReply.DENY;
}
}
return FilterReply.ACCEPT;
}
}
ログ定義
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
…
<filter class="jp.co.ois.hoge.springsecurity.util.SqlLogFilter" />
</appender>
3, 起動時にwarのバージョンをログ出力する
仕組み:起動終了リスナーでServletContextEventからMANIFEST.MFを参照し、ログ出力する。
起動終了リスナー
@WebListener
@Slf4j
public class HogeContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("Starting.");
ServletContext sc = sce.getServletContext();
String metafile = "/META-INF/MANIFEST.MF";
try (InputStream is = sc.getResourceAsStream(metafile)) {
byte[] bytes = is.readAllBytes();
String meta = new String(bytes, StandardCharsets.UTF_8);
meta.lines()
.filter(s -> s.startsWith("Implementation-Version"))
.forEach(this::info);
} catch (IOException e) {
log.error(e.toString(), e);
}
}
private void info(String s) {
log.info(s);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("Shutdown.");
}
}
プロジェクト一式を添付しておきます。
