返回列表 上一筆 下一筆

📄 資料內容

// package: com.example.security

import javax.servlet.*;

import javax.servlet.http.*;

import org.springframework.stereotype.Component;

import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

import java.security.SecureRandom;

import java.util.Base64;



@Component

public class CspNonceFilter extends OncePerRequestFilter {

    private static final SecureRandom RNG = new SecureRandom();



    private static String newNonce() {

        byte[] b = new byte[16]; // 128-bit

        RNG.nextBytes(b);

        return Base64.getEncoder().encodeToString(b);

    }



    @Override

    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)

            throws ServletException, IOException {



        String nonce = newNonce();



        // 給 Thymeleaf 取用

        req.setAttribute("cspNonce", nonce);



        // 建議的 CSP(object-src 改成 none,減少攻擊面)

        String csp = "default-src 'self'; "

                   + "script-src 'self' 'nonce-" + nonce + "'; "

                   + "object-src 'none'; "

                   + "frame-ancestors 'self'";

        resp.setHeader("Content-Security-Policy", csp);



        chain.doFilter(req, resp);

    }

}

🔐 Base64 編碼內容

Ly8gcGFja2FnZTogY29tLmV4YW1wbGUuc2VjdXJpdHkKCmltcG9ydCBqYXZheC5zZXJ2bGV0Lio7CgppbXBvcnQgamF2YXguc2VydmxldC5odHRwLio7CgppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay5zdGVyZW90eXBlLkNvbXBvbmVudDsKCmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLndlYi5maWx0ZXIuT25jZVBlclJlcXVlc3RGaWx0ZXI7CgppbXBvcnQgamF2YS5pby5JT0V4Y2VwdGlvbjsKCmltcG9ydCBqYXZhLnNlY3VyaXR5LlNlY3VyZVJhbmRvbTsKCmltcG9ydCBqYXZhLnV0aWwuQmFzZTY0OwoKCgpAQ29tcG9uZW50CgpwdWJsaWMgY2xhc3MgQ3NwTm9uY2VGaWx0ZXIgZXh0ZW5kcyBPbmNlUGVyUmVxdWVzdEZpbHRlciB7CgogICAgcHJpdmF0ZSBzdGF0aWMgZmluYWwgU2VjdXJlUmFuZG9tIFJORyA9IG5ldyBTZWN1cmVSYW5kb20oKTsKCgoKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBuZXdOb25jZSgpIHsKCiAgICAgICAgYnl0ZVtdIGIgPSBuZXcgYnl0ZVsxNl07IC8vIDEyOC1iaXQKCiAgICAgICAgUk5HLm5leHRCeXRlcyhiKTsKCiAgICAgICAgcmV0dXJuIEJhc2U2NC5nZXRFbmNvZGVyKCkuZW5jb2RlVG9TdHJpbmcoYik7CgogICAgfQoKCgogICAgQE92ZXJyaWRlCgogICAgcHJvdGVjdGVkIHZvaWQgZG9GaWx0ZXJJbnRlcm5hbChIdHRwU2VydmxldFJlcXVlc3QgcmVxLCBIdHRwU2VydmxldFJlc3BvbnNlIHJlc3AsIEZpbHRlckNoYWluIGNoYWluKQoKICAgICAgICAgICAgdGhyb3dzIFNlcnZsZXRFeGNlcHRpb24sIElPRXhjZXB0aW9uIHsKCgoKICAgICAgICBTdHJpbmcgbm9uY2UgPSBuZXdOb25jZSgpOwoKCgogICAgICAgIC8vIOe1piBUaHltZWxlYWYg5Y+W55SoCgogICAgICAgIHJlcS5zZXRBdHRyaWJ1dGUoImNzcE5vbmNlIiwgbm9uY2UpOwoKCgogICAgICAgIC8vIOW7uuitsOeahCBDU1DvvIhvYmplY3Qtc3JjIOaUueaIkCBub25l77yM5rib5bCR5pS75pOK6Z2i77yJCgogICAgICAgIFN0cmluZyBjc3AgPSAiZGVmYXVsdC1zcmMgJ3NlbGYnOyAiCgogICAgICAgICAgICAgICAgICAgKyAic2NyaXB0LXNyYyAnc2VsZicgJ25vbmNlLSIgKyBub25jZSArICInOyAiCgogICAgICAgICAgICAgICAgICAgKyAib2JqZWN0LXNyYyAnbm9uZSc7ICIKCiAgICAgICAgICAgICAgICAgICArICJmcmFtZS1hbmNlc3RvcnMgJ3NlbGYnIjsKCiAgICAgICAgcmVzcC5zZXRIZWFkZXIoIkNvbnRlbnQtU2VjdXJpdHktUG9saWN5IiwgY3NwKTsKCgoKICAgICAgICBjaGFpbi5kb0ZpbHRlcihyZXEsIHJlc3ApOwoKICAgIH0KCn0K
返回列表 上一筆 下一筆