Spring mvc 在Amazon上部署spring boot应用程序的最佳实践
我已经使用Facebook开发了一个聊天机器人应用程序。 我使用嵌入式Tomcat作为web平台。 该应用程序应该运行在AmazonAWS上,对WWW开放,并用作webhook,用于通过https接收来自Messenger的回调 我需要一个如何保护应用程序的建议,这样它就不会被黑客攻击,也不会被来自Facebook以外的请求淹没 我本想让应用程序需要安全(ssl)连接,但在application.properties中使用“security.require\u ssl=true”并没有做到这一点。也许我不知道这是什么意思,以及如何正确地配置它。 是否有一个最佳实践来阻止不是https请求的请求?还是在应用程序级别阻止来自Messenger外部的请求的方法 多谢各位 编辑 同时,我使用handler拦截器阻止了来自应用层中其他IP的请求:Spring mvc 在Amazon上部署spring boot应用程序的最佳实践,spring-mvc,amazon-web-services,spring-security,spring-boot,facebook-messenger,Spring Mvc,Amazon Web Services,Spring Security,Spring Boot,Facebook Messenger,我已经使用Facebook开发了一个聊天机器人应用程序。 我使用嵌入式Tomcat作为web平台。 该应用程序应该运行在AmazonAWS上,对WWW开放,并用作webhook,用于通过https接收来自Messenger的回调 我需要一个如何保护应用程序的建议,这样它就不会被黑客攻击,也不会被来自Facebook以外的请求淹没 我本想让应用程序需要安全(ssl)连接,但在application.properties中使用“security.require\u ssl=true”并没有做到这一点
@Configuration
public class MyWebApplicationInitializer implements WebApplicationInitializer, WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (! (request.getRemoteAddr().equals("173.252.88.66") || request.getRemoteAddr().equals("127.0.0.1")|| request.getRemoteAddr().equals("0:0:0:0:0:0:0:1"))){
logger.warn("Request is not coming from authorized remote address: " + request.getRemoteAddr()+". Rejecting");
response.getWriter().write("Unauthorized Address");
response.setStatus(401);
return false;
} else {
return true;
}
}
}
有很多话要说,所以我相信我会错过一些要点
- 设置SSL是第一件好事,但请确保获得证书。如果您不想为SSL证书付费,这是一件好事 只是aws提供了letsencrypt的替代方案
- 您可以将安全组看作类似于防火墙的东西,这样您就可以控制打开的端口、外部和内部流
- 查看哪些控件谁以及如何访问您的AWS帐户
- 显而易见:更改您的密码。不要让默认密码用于在实例上进行安装
很抱歉这么说,但很可能是这样的-运行扫描器、扫描IP、检查开放端口/暴力登录等不需要是高级黑客…有很多话要说,所以我肯定会错过一些要点
- 设置SSL是第一件好事,但请确保获得证书。如果您不想为SSL证书付费,这是一件好事 只是aws提供了letsencrypt的替代方案
- 您可以将安全组看作类似于防火墙的东西,这样您就可以控制打开的端口、外部和内部流
- 查看哪些控件谁以及如何访问您的AWS帐户
- 显而易见:更改您的密码。不要让默认密码用于在实例上进行安装
很抱歉这么说,但很可能是这样的-运行扫描器、扫描IP、检查开放端口/暴力登录等不需要是高级黑客…您应该检查Facebook发送到您的webhook URL的请求中可用的X-Hub-signature HTTP头 在您的情况下,您可以定义一个过滤器或拦截器来验证签名。您还可以在控制器中执行此操作,如我在spring社交项目中找到的示例所示
private boolean verifySignature(String payload, String signature) throws Exception {
if (!signature.startsWith("sha1=")) {
return false;
}
String expected = signature.substring(5);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
SecretKeySpec signingKey = new SecretKeySpec(applicationSecret.getBytes(), HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(payload.getBytes());
String actual = new String(Hex.encode(rawHmac));
return expected.equals(actual);
}
您应该检查Facebook发送到您的webhook URL的请求中可用的X-Hub-signature HTTP头 在您的情况下,您可以定义一个过滤器或拦截器来验证签名。您还可以在控制器中执行此操作,如我在spring社交项目中找到的示例所示
private boolean verifySignature(String payload, String signature) throws Exception {
if (!signature.startsWith("sha1=")) {
return false;
}
String expected = signature.substring(5);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
SecretKeySpec signingKey = new SecretKeySpec(applicationSecret.getBytes(), HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(payload.getBytes());
String actual = new String(Hex.encode(rawHmac));
return expected.equals(actual);
}
多亏盖伊·布阿莱特的帮助,我加上了签名支票。 我将它添加到我的控制器中,而不是拦截器中,以避免问题看起来有点复杂 这就是:
@RequestMapping(path = "/")
public void doHandleCallback(@RequestBody String body, @RequestHeader(value = "X-Hub-Signature") String signature) throws IOException {
if (!verifyRequestSignature(body.getBytes(), signature)){
logger.error ("Signature mismatch.");
throw new MismatchSignatureException(signature);
}
MessengerCallback callback = mapper.readValue(body, MessengerCallback.class);
logger.info("Incoming Callback: " + body );
for (EventData entry : callback.getEntry()) {
for (ReceivedMessagingObject message : entry.getMessaging()) {
if (message.isMessage() || message.isPostback()) {
doHandleMessage(message);
}
else if (message.isDelivery()){
doHandleDelivery(message);
}
}
}
}
private boolean verifyRequestSignature(byte[] payload, String signature) {
if (!signature.startsWith("sha1="))
return false;
String expected = signature.substring(5);
System.out.println("Expected signature: " + expected); //for debugging purposes
String hashResult = HmacUtils.hmacSha1Hex(APP_SECRET.getBytes(), payload);
System.out.println("Calculated signature: " + hashResult);
if (hashResult.equals(expected)) {
return true;
} else {
return false;
}
}
这是异常处理类:
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Request Signature mismatch")
public class MismatchSignatureException extends RuntimeException {
private String signature;
public MismatchSignatureException(String signature) {
this.signature = signature;
}
@Override
public String getMessage() {
return "Signature mismatch: " + signature;
}
多亏盖伊·布阿莱特的帮助,我加上了签名支票。 我将它添加到我的控制器中,而不是拦截器中,以避免问题看起来有点复杂 这就是:
@RequestMapping(path = "/")
public void doHandleCallback(@RequestBody String body, @RequestHeader(value = "X-Hub-Signature") String signature) throws IOException {
if (!verifyRequestSignature(body.getBytes(), signature)){
logger.error ("Signature mismatch.");
throw new MismatchSignatureException(signature);
}
MessengerCallback callback = mapper.readValue(body, MessengerCallback.class);
logger.info("Incoming Callback: " + body );
for (EventData entry : callback.getEntry()) {
for (ReceivedMessagingObject message : entry.getMessaging()) {
if (message.isMessage() || message.isPostback()) {
doHandleMessage(message);
}
else if (message.isDelivery()){
doHandleDelivery(message);
}
}
}
}
private boolean verifyRequestSignature(byte[] payload, String signature) {
if (!signature.startsWith("sha1="))
return false;
String expected = signature.substring(5);
System.out.println("Expected signature: " + expected); //for debugging purposes
String hashResult = HmacUtils.hmacSha1Hex(APP_SECRET.getBytes(), payload);
System.out.println("Calculated signature: " + hashResult);
if (hashResult.equals(expected)) {
return true;
} else {
return false;
}
}
这是异常处理类:
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Request Signature mismatch")
public class MismatchSignatureException extends RuntimeException {
private String signature;
public MismatchSignatureException(String signature) {
this.signature = signature;
}
@Override
public String getMessage() {
return "Signature mismatch: " + signature;
}
从facebook参考文档中,我看到有可能设置回调令牌(),您配置了吗?您是否在spring应用程序端收到它(作为路径或get参数)?@GuyBouallet该令牌用于首次验证。正在进行的回调不包含任何令牌。你看到我遗漏的东西了吗?你检查过tomcat收到的请求中是否有一个名为X-Hub-Signature的http头吗?@GuyBouallet谢谢!我确实错过了这一点。现在我只需要找出有效载荷和签名的比较。您知道如何从简单的json创建“unicode转义十六进制小写字符串”吗?我相信我也可以使用拦截器,对吗?我添加了一个答案,这样你就可以接受了。请参阅facebook参考文档中的示例实现,我看到有可能设置回调令牌(),您配置了吗?您是否在spring应用程序端收到它(作为路径或get参数)?@GuyBouallet该令牌用于首次验证。正在进行的回调不包含任何令牌。你看到我遗漏的东西了吗?你检查过tomcat收到的请求中是否有一个名为X-Hub-Signature的http头吗?@GuyBouallet谢谢!我确实错过了这一点。现在我只需要找出有效载荷和签名的比较。您知道如何从简单的json创建“unicode转义十六进制小写字符串”吗?我相信我也可以使用拦截器,对吗?我添加了一个答案,这样你就可以接受了。请参阅示例实现。我们的回答给出了有趣的建议,但主要关注AWS服务器端的总体安全。这个问题涉及一个特定的客户,即facebook;因此,确保通信安全需要检查facebook支持什么(SSL+有效负载签名)。您的回答提供了有趣的建议,但总体而言,重点是确保AWS服务器端的安全。这个问题涉及一个特定的客户,即facebook;所以秒