package core.framework.impl.web.site;
import core.framework.api.http.ContentType;
import core.framework.api.http.HTTPStatus;
import core.framework.api.web.Interceptor;
import core.framework.api.web.Invocation;
import core.framework.api.web.Request;
import core.framework.api.web.Response;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
/**
* @author neo
*/
public class WebSecurityInterceptor implements Interceptor { // refer to https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers
@Override
public Response intercept(Invocation invocation) throws Exception {
Request request = invocation.context().request();
if (!"https".equals(request.scheme())) {
return Response.redirect(redirectURL(request), HTTPStatus.MOVED_PERMANENTLY);
} else {
Response response = invocation.proceed();
response.header("Strict-Transport-Security", "max-age=31536000");
response.contentType().ifPresent(contentType -> {
if (ContentType.TEXT_HTML.mediaType().equals(contentType.mediaType())) {
response.header("X-Frame-Options", "DENY");
response.header("X-XSS-Protection", "1; mode=block");
}
response.header("X-Content-Type-Options", "nosniff");
});
return response;
}
}
private String redirectURL(Request request) { // always assume https site is published on 443 port
StringBuilder builder = new StringBuilder("https://").append(request.hostName()).append(request.path());
Map<String, String> queryParams = request.queryParams();
if (!queryParams.isEmpty()) {
int i = 0;
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if (i == 0) builder.append('?');
else builder.append('&');
builder.append(encode(name)).append('=').append(encode(value));
i++;
}
}
return builder.toString();
}
private String encode(String value) {
try {
return URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
}