问题
Consider an application with two entities:
User
(contains basic user data, such as name)Passport
(contains authentication credentials, i.e. password)
And two internal microservices:
UserService
(responsible for creating and managing users and their basic data)AuthService
(responsible for user authentication and password handling)
The User
entity belongs to the UserService
and Passport
entity belongs to the AuthService
.
Those two services should be separated, because they solve very different tasks: profile data and authentication.
Also, consider we have a registration form with three fields:
- Name
- Password
This form will trigger HTTP-request to the GatewayService
, which intercepts all requests to the application and routes them to internal microservices (or composes/aggregates them).
Now, when gateway service receives the request with all the form data it needs to do the following:
- Call
UserService
to create new user (it will respond with generateduserId
). - Call
AuthService
to create a passport for newly created user. It will need theuserId
received in step #1 and apassword
field from the original request.
This looks pretty straightforward, but what will happen if AuthService
is unavailable on step #2? We will need to somehow separate those requests!
The classic approach is to use the eventual consistency and to create Passport
entity via asynchronous call (we can place this request to the queue and process it in separate service). In order to do this we will send an asynchronous request to the AuthService
passing userId
and password
to it, instead of step #2, so the step #1 will immediately return response to the client.
However, what if password
field is not properly formatted (breaks validation rules)? The validation logic is only present in the AuthService
, so we can't know if password is correct until the call is made to it. And now, the request is processed asynchronously, so we can't get back to user and tell him to correct the password.
SO, how do you properly handle validation in distributed composite requests to microservice application?
The naive solution is to move validation logic to the
GatewayService
itself, but it's a terrible idea, because it will make it fat and will leak business logic fromAuthService
.The other idea is to provide an additional method for password validation and to call it prior to steps #1 and #2. It looks like a viable solution, but it will force us to have two methods for each business method in our microservices, one for prior validation and one for actual operation. Also, there is a time space between validation and operation, so the earlier correct value could become incorrect when operation is actually performed.
We could split the form in two to avoid composite requests and ask user for password after asking for personal data and creating an account for him. However, this could lead to security problems, where user account could be intercepted by some other party who could guess the next
userId
. We could, use some additional security token, but it will introduce odd functionality to services and will make the whole setup more complex.Also, this approach looks like an attempt to escape the problem, you can't always avoid composite requests.
We could use full-scale distributed transactions, e.g. 2PC, but it will make the system dramatically complex and will mitigate the use of MSA in the first place.
And the final idea is to merge those two services together, but it will make no sense in microservice architecture to do so.
回答1:
Here is my thought
1.User Service - should be responsible for
Creation of user which includes user name ,password (hashed) , email and any other profile data
validation of input data against validation rules
validation of user using his password
pros
further adition of profile data is easy
finding and validatng user in single request
user related login in single place
2.Authentication Service should be responsible only to generate tokens based upon successful user validation via user service
these token should be used for further processing by all other services in ecosystem and will make sure proper authorisation
pros
future addition of services that will require user authentication and authorisation can work independently and will require only security token.
Generation of token based on previous token can be easy ,user will not need to enter his user name and password each time his token is about to expire.
回答2:
Regarding #5, I really don't see that you are somehow committing a horrible violation of principles by merging into one service here (point 5), a kind of “UserManagementService” that takes care of both tasks; even if it can be argued that one MS should perform one task and do it well, these two are intimately related, IMHO.
Another option is to make UserService a sync client of AuthService (load balanced, with circuit breaker, whatever, to ensure availability of one instance), which would be basically the same as injecting the dependency for a password validation in "normal" code.
If this is a greenfield thing and you are not stuck with these two services, in general, I would go for a simpler first implementation, and resist the impulse for optimizations, as these tend to be premature, or a unwarranted commitment to the purity of principles/dogmas. You yourself are aware of the complexities you could introduce (2PC) plus you have your requirement there ("so we can't get back to user and tell him to correct the password").
回答3:
I agree with #5. The two services will have many dependencies since accessing UserService will always relate to AuthService, and they probably access related data. If you separate them you may need to separate their shared logic like generating the passport. It can be in a service that has an operation that receives a userID either from AuthService (after validating credentials) or from UserService (after registration).
Also handling the absence of AuthService will raise questions about other scenarios, like if the user already registered and cannot login, how do you handle it?.. If you're showing an error message, why not when they register?.. just a question for more thoughts about your requirements.
Cheers
来源:https://stackoverflow.com/questions/42981194/how-do-you-handle-validation-in-composite-microservice-request