Play Framework 2.6(Scala)内联JavaScript无法运行遇CSP报错求助
Got it, let's break down how to fix that Content Security Policy (CSP) error you're seeing. Play Framework 2.6+ enables a strict default CSP to protect against XSS attacks, which is why your inline JavaScript is getting blocked. Here are the three most common solutions, ordered by security best practice:
1. Use a Nonce (Recommended for Dynamic Inline Scripts)
A nonce is a unique, random value generated per request—this is the most secure approach because only scripts with the matching nonce will execute.
Step 1: Generate the Nonce in Your Controller
Add code to create a secure nonce and attach it to both the response header and your template:
import play.api.mvc._ import java.security.SecureRandom import java.util.Base64 class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController { // Reuse a secure random instance for efficiency private val secureRandom = new SecureRandom() def index() = Action { implicit request: MessagesRequest[AnyContent] => // Generate a 16-byte nonce, base64-encoded val nonce = Base64.getEncoder.encodeToString(new Array[Byte](16)) // Pass the nonce to your template and set the CSP header Ok(views.html.index(nonce)).withHeaders( CONTENT_SECURITY_POLICY -> s"default-src 'self'; script-src 'self' 'nonce-$nonce';" ) } }
Step 2: Reference the Nonce in Your HTML Template
Add the nonce attribute to your inline script tag, using the value passed from the controller:
<script nonce="@nonce"> // Your inline JavaScript here console.log("Inline script now runs with nonce!"); </script>
2. Use a Script Hash (For Static Inline Scripts)
If your inline script never changes, you can use its SHA-256 hash (which the error message already provided: sha256-DdH/amfJizOgk2xZ+Xst5j13qHxPYrrrfT6x/TzfYiA=).
Update Your Controller's CSP Header
Add the hash to the script-src directive:
def index() = Action { implicit request: MessagesRequest[AnyContent] => Ok(views.html.index()).withHeaders( CONTENT_SECURITY_POLICY -> "default-src 'self'; script-src 'self' 'sha256-DdH/amfJizOgk2xZ+Xst5j13qHxPYrrrfT6x/TzfYiA=';" ) }
Note: If you modify the inline script later, you'll need to recalculate the hash and update the CSP.
3. Use unsafe-inline (Only for Development)
⚠️ Never use this in production—it disables a key security layer against XSS attacks. This is only for quick testing in a local dev environment:
def index() = Action { implicit request: MessagesRequest[AnyContent] => Ok(views.html.index()).withHeaders( CONTENT_SECURITY_POLICY -> "default-src 'self'; script-src 'self' 'unsafe-inline';" ) }
Bonus: Global CSP Configuration
Instead of setting the CSP header per controller, you can define a base policy in application.conf, though you'll still need to inject dynamic values like nonces in controllers:
play.filters.headers.contentSecurityPolicy = "default-src 'self'; script-src 'self'"
内容的提问来源于stack exchange,提问作者zamsler

