しおメモ

雑多な技術系ブログです。ニッチな内容が多いです。

memo: CentOS7系のfirewalld

firewalld

CentOS6系までのiptablesの代わりに、7系からではfirewalldを用います。
中身はiptablesのままらしいです。

設定の操作はfirewall-cmdを用います。

バージョン

CentOS Linux release 7.5.1804 (Core)

共通操作

現在の設定の確認

firewall-cmd --list-all

こんな感じで出ます。

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh dhcpv6-client
  ports:
  protocols:
  forward-ports:
  source-ports:
  icmp-blocks:

設定再読み込み

一時的な設定を破棄して、設定を再読み込みをするときは、

firewall-cmd --reload

systemctlでもいけます。

systemctl restart firewalld

各種設定

サービス追加

httphttpsなどの元からデフォルト値があるものは、 add-serviceで追加すると、対応するポート(80,443...)を開けてくれます。

firewall-cmd --add-service=http

ポート追加

それ以外の物は、ポート番号を指定して開ける事ができます。

firewall-cmd --add-port=1234/tcp

永続設定

firewalldが再起動した場合にも残る設定をしたいときは、--permanentをつけます。

firewall-cmd --add-port=1234/tcp --permanent

Zone

設定値をまとめたプロファイルのようななものです。
デフォルトではpublicになっていますが、 zoneごとに設定を変えて、異なるネットワークインターフェースに適用したりできます。

デフォルトゾーンの変更

# externalの初期値ではsshのみ許可されます
firewall-cmd --set-default-zone=external

設定値変更

firewall-cmd --zone=external --add-service=http --permanent

Springのcontrollerにおけるvalidation

Spring Frameworkにおけるvalidation

http://terasolunaorg.github.io/guideline/5.4.1.RELEASE/ja/ArchitectureInDetail/WebApplicationDetail/Validation.html

詳しくは上記リンクも参照したほうが良いですが、 カジュアルに使うように残します。

Hibernate Validator

実装はHibernate Validatorなので、javax.validation.constraintsアノテーションを使います。

主なアノテーション

@NotNull // nullでないことをチェック

/**
* Stringに対して使えるアノテーション
*/
@NotEmpty // 空文字列でないことをチェック
@Size(min = 1, max = 10) // 文字列の長さが1以上10以下であることをチェック
@Pattern(regexp = "[0-9A-Z]*") // "[0-9A-Z]*"の正規表現にマッチしているかチェック
@Email // Emailアドレスとしてvalidなものかチェック

/**
* Integerなど整数型に対して使えるアノテーション
*/
@Min(3) // 3以上であることをチェック
@Max(100) // 以下であることをチェック

Formに対するvalidation

制約を記したFormクラスを用意して、コントローラで受け取るのが基本です。

Formクラス

ビューの入力フォームに対応するFormクラスを書きます。

@Data
public final class SearchForm {
    @NotNull
    @Size(min = 1, max = 100)
    @Pattern(regexp = "[0-9a-zA-z]*")
    private String message;
}

Controllerクラス

Formのバリデーションに失敗するとBindingResultにエラーが入ります。

@Controller
@RequestMapping("")
public class SearchController {
    @PostMapping("serach")
    public ModelAndView search(
        @Validated @ModelAttribute final SearchForm searchForm,
        final BindingResult bindingResult
    ) {
        final ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("hoge");
        // Formのバリデーションに失敗するとBindingResultにエラーが入る
        if (bindingResult.hasErrors()) {
            // エラー時の処理
        }

        // ...

        return modelAndView;
    }
}

エラー時の実際の処理は、エラーページに飛ばしたり、 modelに何かを付け加えたりといったものになります。

エラーメッセージは、デフォルトで親切なものが出ます。
Constraintごとにmessage属性を付与して、カスタムすることができますが、
セキュリティ上の懸念がある場合は、modelに付与して、一括で同じメッセージを出しても良いと思います。

Form以外に対するvalidation

Form以外の普通の引数に対するvalidationでも、不正なリクエストを弾く場合などで、Hibernate Validatorは有用です。

@Controller
@RequestMapping("")
public class HogeController {
    @PostMapping("add")
    public ModelAndView add(
        @RequestParam("quantity")
        @NotNull
        @Min(1)
        @Max(100)
        @Valid final Integer quantity) {

        // ...

    }
}

(ここの場合Springの@Validatedではなく、Hibernateの方の@ValidでもOKです)

ここでinvalidだった場合、中に入る前に、javax.validation.ConstraintViolationExceptionが投げられます。

Springの場合はControllerで投げられた例外は@ExceptionHandlerで拾うことができるので、
@ControllerAdviceの中に書いておけば、全ての@Controllerから投げられたConstraintViolationExceptionを拾うことができます。

@ControllerAdvice
public class MyExceptionHandler {
    // 400 Bad Requestを返してエラーページに飛ばす
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleConstraintViolationException() {
        // ログ落としたり...
        
        return "error";
    }
}

書いてないこと

自前のconstraint annotationを作ることもできます。
長くなったので、また今度ということで… (忘れる😩)

Lombokはいいぞ

Lombokとは

いい感じにAnnotaitionで、Javaのよく出てくる処理を書いてくれるやつ。
使うと世界が変わる。

網羅的にざっと書きます。

共通テク

うまくいかなかったらIDEのDelombokでバラして考えてみる。
ドキュメントも充実している。

よく使う

@Getter, @Setter

https://projectlombok.org/features/GetterSetter

名前の通りGetter,Setterを自動で作ってくれる。
クラスにもフィールドにも使用可能で、final修飾されたフィールドのSetterはもちろん作られない。

@Getter @Setter
public class Hoge {
    private int val;

    // ここにgetVal(), setVal(int val)みたいなのが作られるイメージ
}

フィールドだと、

public class Hoge {
    @Getter @Setter
    private int val;
}

残念ながらsynchronized相当のものは作れない。

@ToString

https://projectlombok.org/features/ToString

クラスの先頭につけると、toStringのオーバーライドメソッドがいい感じに生成される。
迷ったらつけとけばいいと思う。

@ToStirng
public class Hoge {
    private int val;
    private String hoge;

    // @Override public String toString() が生成される
}

循環参照でハマったりしてtoStringで出したくないフィールドがあるときは、

@ToString
// あるいはここで、@ToString(exclude = "secret")
public class Hoge {
    private int val;
    @ToString.Exclude private String secret;
}

こんな感じで指定する。

@EqualsAndHashCode

https://projectlombok.org/features/EqualsAndHashCode

equalsを用意するときにはhashCodeも用意しようということで、いっぺんにやってくれるやつ。
迷ったらつける。

@Data

https://projectlombok.org/features/Data

ここまでやった奴を全部つけてくれるアノテーション
@Setter@Getter@ToString@EqualsAndHashCode@RequiredArgsConstructorをつけてくれる。

@Data
public class Hoge {
    private int var;
    private String hoge;

    // get, set, toString, equals, hasCode, canEqualsができる
    // この場合Hoge()もできる。詳細は後述
}

めんどくさいときは、これだけつけておけばOK。
@RequiredArgsConstructorについては後述。

@xxxArgsConstructor

https://projectlombok.org/features/constructor

  • @NoArgsConstructor
  • @AllArgsConstructor
  • @RequiredArgsConstructor

この3種類がある。 クラスの先頭につけると、 @NoArgsConstructorは引数なしのコンストラクタ、 @AllArgsConstructorは全てのフィールドと対応する引数を持つコンストラクタを生成する。

@RequiredArgsConstructorfinalフィールドに対してのみ初期化を行うコンストラクタを生成する。

@RequiredArgsConstructor
public class Hoge {
    private final int val;
    private String hoge;

    /*
    このようなコンストラクタができる
    public Hoge(int val) {
        this.val = val;
    }
    */
}

@NonNull

https://projectlombok.org/features/NonNull

nullチェックを生成する。引数にnullが入ってきた時点でNullPointerExceptionを吐いて落とす。
引数が多くなってくると、nullチェックも多くなってくるのでアノテーションでできると便利。

// nullが入ってきたら中に入る前に落としてくれる
pubilc void hoge(@NonNull final String message) {
    message.hashCode();
}

知らなくても困らないやつ

@Builder

https://projectlombok.org/features/Builder

Builderパターンを自動生成する。

@Builder
public class Hoge {
    private int val;
    private String name;

    // ごちゃごちゃBuilderパターンができる
}

使うときは、

Hoge hogehoge = Hoge.builder()
    .val(1)
    .name("a")
    .build();

TPOに合わせて使うと便利かも。

@SneakyThrows

https://projectlombok.org/features/SneakyThrows

問題児

チェック例外を非チェック例外をとして、ある意味握りつぶす。
使いどころは、コード上チェック例外が起こり得ないけど、Javaの仕様的にtry catchを書くのを強いられて、めんどくさい時(ということだと思う)。

rethrowみたいなの自作する時とかにも使えるかもしれない…。

普通に実装するのも、そんなに大変ではなさそう。

@SuppressWarnings("unchecked")
public static <E extends Throwable> void sneakyThrow(Throwable e) throws E {
    throw (E) e;
}

@Slf4j

つけるとSlf4jのloggerを作ってくれる。

@Slf4j
public class Hoge {
    // これができる
    // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Hoge.class);
}

ありがたみが薄い。

まとめ

Lombok使うとJavaが楽しくなります。