微服务安全 [英] Micro service security
问题描述
在过去的几天我一直在玩微服务模式,一切都进展顺利,但安全性似乎难不倒我。
Over the last few days I've been playing with the micro service pattern and all is going well but security seems to baffle me.
<击>
所以如果我可以问一个问题:
如何处理对个人服务的用户身份验证?目前,我传递给网关API
这反过来连接到服务的请求。
击>
So If I may ask a question:
How do I handle user authentication on an individual service? At the moment I pass a request to the Gateway API
which in turns connects to the service.
问编辑请参考下面
铭记各个服务不应该知道对方。在网关
是聚合本身。
Bearing in mind that the individual services should not know about each other. The Gateway
is the aggregator as such.
当前架构
一个小代码模拟了请求:
A little code to simulate the request:
前端 - 客户端应用
public class EntityRepository<T>
{
private IGateway _gateway = null;
public EntityRepository(IGateway gateway)
{
this._gateway = gateway;
}
public IEnumerable<T> FindAll()
{
return this._gateway.Get(typeof(T)).Content.ReadAsAsync<IEnumerable<T>>().Result;
}
public T FindById(int id)
{
return this._gateway.Get(typeof(T)).Content.ReadAsAsync<T>().Result;
}
public void Add(T obj)
{
this._gateway.Post(typeof(T), obj);
}
public void Update(T obj)
{
this._gateway.Post(typeof(T), obj);
}
public void Save(T obj)
{
this._gateway.Post(typeof(T), obj);
}
}
//Logic lives elsewhere
public HttpResponseMessage Get(Type type)
{
return Connect().GetAsync(Path(type)).Result;
}
public HttpResponseMessage Post(Type type, dynamic obj)
{
return Connect().PostAsync(Path(type), obj);
}
private string Path(Type type)
{
var className = type.Name;
return "api/service/" + Application.Key + "/" + className;
}
private HttpClient Connect()
{
var client = new HttpClient();
client.BaseAddress = new Uri("X");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
我使用泛型,以确定它需要火,一旦它击中的网关。
因此,如果键入
的类别将火在类别服务并进而呼吁:
I use generics to determine where it needs to fire once it hit's the gateway.
So if the Type
is Category it will fire the Category service thus calling:
public IEnumerable<dynamic> FindAll(string appKey, string cls)
{
var response = ConnectTo.Service(appKey, cls);
return (appKey == Application.Key) ? (response.IsSuccessStatusCode) ? response.Content.ReadAsAsync<IEnumerable<dynamic>>().Result : null : null;
}
网关不包含物理文件/文件类型的类的。
The Gateway does not contain the physical files/Class's of the types.
一些代码后,我希望有人可以给我一些示范或处理与当前架构的安全性/用户认证的最佳方法。
After a little code, I was hoping someone could give me a little demonstration or the best approach to handle security/user authentication with the current architecture.
案例情景1
用户点击在Web应用程序和日志,在这一点上用户加密的电子邮件和密码发送到网关API
,然后传递到用户服务
并决定用户是否经过验证 - 一切都很好,但现在我想获取所有信息从消息服务
用户已收到。我无法在网关真说,如果用户通过验证,获取信息,因为不解决呼叫问题的消息服务
之外网关API
Case Scenario 1
User hits the web app and logs in, at that point the users encrypted email and password is sent to the Gateway API
which is then passed to the User Service
and decides whether the user is authenticated - all well and good but now I want to fetch all Messages from the Message Service
that the user has received. I cannot really say in the Gateway if the user is authenticated, fetch the messages because that does not solve the issue of calling the Message Service
outside of the Gateway API
我也可以不加验证每一个人服务,因为这需要谈话的用户都各自服务。服务
和击败模式的目的
I also cannot add authentication to each individual service because that would require all respective services talking to the User Service
and that defeats the purpose of the pattern.
修正:
只允许网关调用服务。请求外部网关应阻止的服务。
Fixes: Only allow the Gateway to call the Services. Requests to services outside of the Gateway should be blocked.
我知道安全性是一个广泛的话题,但在当前背景下,我希望有人能告诉我最好的行动方针来解决问题。
I know security is a broad topic but within the current context, I'm hoping someone could direct me with the best course of action to resolve the issue.
目前我已经全部关闭应用程序,它在硬编码一个的Guid
如果应用程序是平等反过来获取数据。
Currently I have Hardcoded a Guid
in all off the applications, which in turn fetches data if the app is equal.
推荐答案
修改的
Edit
的这个答案是对网关< - >科技的服务,沟通。用户当然应该正确验证当与网关应用会谈的
结束编辑的
end edit
首先,微服务不应从互联网可到达的。它们应该只从网关(可群集)进行访问。
First of all, the micro services should not be reachable from internet. They should only be accessible from the gateway (which can be clustered).
其次,你需要能够识别当前用户。你可以通过在用户ID
作为HTTP头做。创建的WebAPI过滤器,它采用了头,并从它创建一个自定义的的IPrincipal
。
Second, you do need to be able to identify the current user. You can do it by passing the UserId
as a HTTP header. Create a WebApi filter which takes that header and creates a custom IPrincipal
from it.
最后,你需要一些方法来确保该请求来自网关或另一个微服务。一个简单的方法是在一个令牌使用HMAC认证。
Finally you need some way to make sure that the request comes from the gateway or another micro service. An easy way to do that is to use HMAC authentication on a token.
存储在的web.config
为每个服务和网关的关键。然后,只需发送与每个请求令牌(你可以使用的WebAPI认证过滤器认证)
Store the key in the web.config
for each service and the gateway. Then just send a token with each request (which you can authenticate using a WebApi authentication filter)
要生成一个散列,使用 HMACSHA256
在.NET类:
To generate a hash, use the HMACSHA256
class in .NET:
private static string CreateToken(string message, string secret)
{
secret = secret ?? "";
var keyByte = Encoding.ASCII.GetBytes(secret);
var messageBytes = Encoding.ASCII.GetBytes(message);
using (var hasher = new HMACSHA256(keyByte))
{
var hashmessage = hasher.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
因此,在你的 MicroServiceClient
你会做这样的事情:
var hash = CreateToken(userId.ToString(), mySharedSecret);
var myHttpRequest = HttpRequest.Create("yourUrl");
myHttpRequest.AddHeader("UserId", userId);
myHttpRequest.AddHeader("UserIdToken", hash);
//send request..
和在微服务,你创建了一个过滤器:
And in the micro service you create a filter like:
public class TokenAuthenticationFilterAttribute : Attribute, IAuthenticationFilter
{
protected string SharedSecret
{
get { return ConfigurationManager.AppSettings["SharedSecret"]; }
}
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
var userId = context.Request.Headers.GetValues("UserId").FirstOrDefault();
if (userId == null)
{
context.ErrorResult = new StatusCodeResult(HttpStatusCode.Forbidden, context.Request);
return;
}
var userIdToken = context.Request.Headers.GetValues("UserIdToken").FirstOrDefault();
if (userIdToken == null)
{
context.ErrorResult = new StatusCodeResult(HttpStatusCode.Forbidden, context.Request);
return;
}
var token = CreateToken(userId, SharedSecret);
if (token != userIdToken)
{
context.ErrorResult = new StatusCodeResult(HttpStatusCode.Forbidden, context.Request);
return;
}
var principal = new GenericPrincipal(new GenericIdentity(userId, "CustomIdentification"),
new[] {"ServiceRole"});
context.Principal = principal;
});
}
public async Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
}
public bool AllowMultiple
{
get { return false; }
}
private static string CreateToken(string message, string secret)
{
secret = secret ?? "";
var keyByte = Encoding.ASCII.GetBytes(secret);
var messageBytes = Encoding.ASCII.GetBytes(message);
using (var hasher = new HMACSHA256(keyByte))
{
var hashmessage = hasher.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
}
这篇关于微服务安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!