2025年3月15日土曜日

Maven で Servlet 開発する

新人研修で JSP&Servlet をやるっぽいので素振りをした。

前提

  • Docker: Docker version 27.4.0, build bde2b89
  • 使用コンテナ: maven:3, tomcat:11

compose.yaml の作成

services:
  app:
    image: maven:3
    volumes:
      - .:/workspaces
      # tomcat11 との共有ディレクトリ
      # ビルドした war ファイルをここに格納する
      - firststep-webapps:/tomcat-webapps
    command: "sleep infinity"
  tomcat:
    image: tomcat:11
    volumes:
      - firststep-webapps:/usr/local/tomcat/webapps
    ports:
      - 8080:8080
volumes:
  firststep-webapps:
    driver: local

開発環境の起動

docker compose up -d

開発環境へ接続

docker compose exec app bash

Maven プロジェクトの作成

ひな形の作成

mvn archetype:generate -DgroupId=dev.mikoto2000.study.servlet -DartifactId=firststep -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

ただし、このプロジェクトは依存が足りなかったり Servlet が jakarta になる前のものだったりするので、 pom.xmlweb.xml を修正する。

pom.xml の修正

${PROJECT_ROOT}/pom.xml に以下依存を追加する。

    <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>6.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
    <dependency>
      <groupId>jakarta.servlet.jsp.jstl</groupId>
      <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
      <version>3.0.2</version>
    </dependency>

web.xml の修正

${PROJECT_ROOT}/src/main/webapp/WEB-INF/web.xml を修正。

before:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

after:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <display-name>MyApp</display-name>
</web-app>

開発

実装

${PROJECT_ROOT}/src/main/java/dev/mikoto2000/study/servlet/firststep/HelloServlet.java に Servlet を実装する。

package dev.mikoto2000.study.servlet.firststep;

import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      response.getWriter().println("<h1>Hello, Servlet!</h1>");
  }
}

ビルド

mvn package

${PROJECT_ROOT}/target/firststep.war が作成される。

デプロイ

/tomcat-webapps が tomcat のアプリデプロイディレクトリと共有されているので、 war ファイルをそこにコピーする。

cp target/firststep.war /tomcat-webapps/

動作確認

http://localhost:8080/firststep/hello へアクセスすると、 Hello, Servlet! が表示される。

以上。

2025年2月28日金曜日

Vim でカーソル下の文字コード取得と文字コードでの入力を行う

使いどころはパッと思いつかないけど、過去に何度かお世話になったので備忘録として記す。

カーソル下の文字コード取得

ga コマンドで取得できる。

例えば、 にカーソルを合わせて ga を押すと、以下のように情報が表示される。

<→ > 8594, Hex 2192, Oct 20622, Digr ->

文字コードでの入力

インサートモード中に <C-v> を押すことで、文字コードによる入力ができる。

例えば、前述の を入力したい場合には i<C-v>u2192 と入力する。

以上。

参考資料

2025年2月11日火曜日

Spring Boot で SAML 認証をする(署名無しバージョン)

前提

  • Java: 21
  • Spring Boot: 3.4.2
  • Keycloak: 26

開発環境の起動

詳細は docker-compose.yaml を参照。

Spring Initilizr

this

Keycloak の設定

  1. http://localhost:8080/ へ接続し、以下情報でログイン
    • ユーザー名: admin
    • パスワード: password
  2. レルムの作成
    • レルム名: myrealm
  3. クライアントの作成
    1. Clients > Create client
      • Client type: SAML
      • Client ID: saml-sp
      • Name: SAML Practice
    2. Settings タブで必要事項を設定
      • Root URL: http://localhost:8081/
      • Valid redirect URIs: http://localhost:8081/*
    3. Keys タブで必要事項を設定
      • Client signature required: Off
  4. ユーザーの追加
    1. Users > Add user で、必要事項を記入して Create 押下
      • Username: test
    2. Credentials タブで Set password を押下し、必要事項を記入し Save
      • Password: test
      • Password confirmation: test
      • Temporary: Off

依存を追加

pom.xml に Shiboleth のリポジトリを追加し、 spring-security-saml2-service-provider の dependency を追加する。

<repositories>
  <repository>
    <id>shibboleth</id>
    <name>Shibboleth Repository</name>
    <url>https://build.shibboleth.net/nexus/content/repositories/releases/</url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>
...(snip
  <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-saml2-service-provider</artifactId>
  </dependency>
...(snip

Security のコンフィギュレーションを作成

package dev.mikoto2000.study.saml.firststep.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
      .authorizeHttpRequests(auth -> auth
          .requestMatchers("/", "/public").permitAll()
          .anyRequest().authenticated()
          )
      .saml2Login(saml2 -> saml2
          .loginProcessingUrl("/login/saml2/sso/myrealm")
          )
      .logout(logout -> logout
          .logoutSuccessUrl("/")
          );
    return http.build();
  }
}

署名に使うファイル群の作成

# 1. 秘密鍵を作成
openssl genpkey -algorithm RSA -out private.key

# 2. 証明書リクエストを作成
openssl req -new -key private.key -out cert.csr \
    -subj "/C=JP/ST=Tokyo/L=Shibuya/O=ExampleCorp/OU=IT/CN=localhost"

# 3. 証明書を発行
openssl x509 -req -days 3650 -in cert.csr -signkey private.key -out certificate.crt

# 4. 秘密鍵と証明書をクラスパス直下に移動
mv certificate.crt private.key ./src/main/resources/

アプリケーション設定

spring:
  security:
    saml2:
      relyingparty:
        registration:
          myrealm:
            # Keycloak の Client ID と合わせる
            entity-id: "saml-sp"
            signing:
              credentials:
                # さっき作った証明書などの情報を入力
                - private-key-location: "classpath:private.key"
                  certificate-location: "classpath:certificate.crt"
                  private-key-password: "changeit"
                  private-key-alias: "saml-key"
                  key-store-password: "changeit"
            assertingparty:
              metadata-uri: "http://keycloak:8080/realms/myrealm/protocol/saml/descriptor"

# デバッグ出力を有効化
logging:
  level:
    org:
      springframework.web: debug

# Keycloak とポートがかぶるのでこっちを変更
server:
  port: 8081

表示するページの作成

以下静的ページを src/main/resources/static 下に格納する。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>test</title>
</head>
<body>
  Hello, World!
</body>
</html>

hosts ファイルの更新

hosts ファイルに以下エントリーを追加。

127.0.0.1 keycloak

動作確認

  1. http://localhost:8081/index.html へ接続すると、 keycloak へリダイレクトされる
  2. 先ほど作った test ユーザーでログインすると、 index.html が表示される

OK.