I need to restrict method execution with specific parameters.
F.e. some seller can create bill for customer id=1 but can't for customer id=2.
Is it possible implement in spring security or I should make check in business logic code?
There are multiple options here:
You can use Spring Security ACL module to take into account actual domain object for your security restrictions. It is a good option when you have multiple security rules like this.
If you have only one security rule like this then using ACL module may be an overkill. In this case it will be better to make check in your business code. You have two options to call this code:
Call it declaratively using annotation. You will be able reuse this check more easy, but you lose control over raised exception (it will be default AccessDeniedException):
#PreAuthorize("hasRole('ROLE_AAA') and #billValidatorBean.validateForCustomer(#customerId)")
public createBill(Integer customerId, ...) {
Or implement it in corresponding method directly which gives you complete control over everything.
Choose your way depending on situation.
Related
Spring Data REST has been working exceptionally well for me, but I need to be able to restrict what parameters the user may provide when creating certain resources. For instance, the user should not be able to dictate the ID assigned to the created resource or the activation state of an account, let's say.
My approach to this so far is simply to clear or reset these fields manually in a repository #HandleBeforeCreate event handler. Is there another, more clever option for restricting the accepted POST data for a resource?
Additionally, there are cases where a CRUD call needs to specify additional, contextual attributes that are not explicitly part of the target resource but may be used in the process of creating the resource. What is the appropriate way to handle this case?
You can define a custom validator by implementing org.springframework.validation.Validator and override validate(Object object, Errors errors) and validate the input fields and then populate or make necessary changes to the fields as required to the input request object.
You can refer here for more details and also here for an example.
I'm new to Spring JPA/jHipster.
My question is inspired by the jHipster talk by Julien Dubois: https://youtu.be/R3jm2qmqctI?t=43m7s
Assume you have a bank account with operations on it (+100$ for restaurant, -50$ ATM, ...)
Each bank account has an owner of course.
The payload of a POST REST call that creates the operation could look like this:
{"amount":100,"description":"restaurant","bankaccount":{"id":1136}}
The id of the bankaccount is unique and (for the sake of this example) would have been sent to me earlier via another REST call.
Unfortunately, nothing prevents a malicious user to change this value. One could simply guess the id of a bankaccount owned by someone else, and then the operation would be added to that one.
I have not (yet) seen examples that deal with this problem.
Should I explicitly check if the bankaccount is owned by the user?
I imagine that this type of verification may cascade through all your entities, causing a lot of extra calls.
Maybe I'm missing something?
Thanks,
Andy
Yes it's your reponsibility to check in your REST controller or underlying services that an operation is authorized. Spring security offers different mechanisms to do it in particular by using #PreAuthorize and #PostFilter.
It's also a good thing to use DTOs, this way you can better control what fields of your entities are exposed for reading and writing through the API.
It's a code design question :)
I have a DelegatingHandler which takes the http request header and validates the API-key. Pretty common task I guess. In my controller I call my business logic and pass along all business-relevant information. However now I'm challenged with the task to change behavior inside my business logic (separate assemblies) depending on certain api-keys.
Various possible solutions come to my mind...
Change business logic method signatures to ask for an api-key, too.
public void SomeUseCase(Entity1 e1, Entity2 e2, string apiKey);
Use HttpContext.Current to access the current request context. However I read somewhere that using HttpContext restrict my hosting options to IIS. Is there any better suited option for that?
var request = HttpContext.Current.Request; // next extract header information
Use Sessions (don't really want to go that road...)
What's your opinion on that topic?
I'd go for #1 although I don't like the idea of mixing in enivonmental stuff in business logic methods. But depending on your point of view you might argue the api-key is in fact logic-relevant.
Update #1:
I'm using a delegatingHandler to validate the apiKey and once it is validated I add it to the Request's Properties Collection.
The part in question is how the "api-key" or RegisteredIdentifier is passed along to the business logic layer. Right now I am passing the object (e.g. IRegisteredIdentifier) as a parameter to the business logic classes' constructors. I understand there is no more elegant way to solve this(?). I thought about changing the method signatures but I'm not sure whether it's interface pollution or not. Some methods need to work with the api-key, most don't. Experience tells me that the number will more likely grow than drop :) So keeping a reference to it in my bl classes seems to be a good choice.
Thank you for your answers - I think all of them are part of my solution. I'm new to StackOverflow.. but as far as I can see - I cannot rate answers yet. Rest assured I'm still thankful :)
I would suggest two different options.
Promote the value into a custom HTTP header (e.g. something like mycompany-api-key: XXXX ). This makes your delegating handler work more like a standard HTTP intermediary. This would be handy if you ever hand off your request to some secondary internal server.
Put the api-key into the request.Properties dictionary. The idea of the the Properties dictionary is to provide a place to put custom meta information about the request.
HTTP works hard to make sure authentication/authorization is a orthogonal concern to the actual request, which is why I would try and keep it out of the action signature.
I would go for option 1.
But you could introduce the entity RegisteredIdentifier (Enterprise Patterns and MDA by Jim Arlow and Ila Neustadt) in your business logic.
The api-key can be converted to a RegisteredIdentifier.
RegisteredIdentifier id = new RegisteredIdentitief(api-key);
public void SomeUseCase(Entity1 e1, Entity2 e2, RegisteredIdentifier id);
The business logic layer has a dependency on the API key. So I would suggest:
interface IApiKeyProvider
{
string ApiGet { get; }
}
..then have your BLL require that an object implementing that interface is supplied to it (in constructor, setup, or even each method that requires it).
Since in the future it might not be one API key. The key point is that this identifies the BLL is dependent on something, and defining a contract for the something.
Real-world example:
Then, in your DI container (Ninject etc), bind your own ConfigFileApiKeyProvider (or whatever) implementation to that interface, in the "place" (layer) that DOES have the API key. So the app that calls the BLL specifies/configures how the API key is specified.
Edit: I misunderstood the part about this being a "how-to-do-it-over-HTTP" question and not a code architecture/code design question. So:
HTTP header is the way to go in terms of transport
We have a few features that follow very similar patterns:
User submits email address
User receives email with secret code
User redeems secret code to perform secure action
For example, our sign-up / registration feature follows this pattern. User submits email address, receives email, then uses secret code to create password & user account. Another example is password reset. User submits email address, receives email, then uses secret code to change password and access user account.
Pattern #1
We could have 1 controller that manages each feature individually. So, for example, a SignUpController that handles all related actions (sending email, redeeming code, and creating password). Then we could have a PasswordResetController that also handles sending the email, redeeming the code, and changing the password.
Pattern #2
An alternative would be to have the actions split across controllers. In this pattern, we would have a SendEmailController that would send emails for both features, a CodeRedemptionController that would handle code redemptions for both features, and a PasswordController that would handle password operations for both features.
Which is a better approach and why? Our main goals are to achieve high code simplicity, clarity / discoverability, and DRYness. I can see advantages and disadvantages with both patterns.
Pattern #1 advantages
All code pertaining to the feature is kept in one place. Passing data from one action to another using TempData dictionary is easier to understand, and the flow of the feature is described by a single controller.
Pattern #1 disadvantages
Dependency injection. Each feature controller would need dependencies injected for email sender, account manager (MembershipProvider interface wrapper), as well as various repositories. When using constructor injection, the constructor would have a lot of arguments.
The advantages and disadvantages of Pattern #2 would be the opposite. We could simplify dependencies for the controllers, but the features would be spread across multiple controllers, blurring the clarity of what features the app as a whole is trying to achieve.
I would use a single account controller to manage all of the related user management functions. This controller would be the user's access point to handle these types of features.
Then I would separate the separate logic you mentioned into different model classes that would be called by that controller as needed. Examples:
/models/EmailManager.cs
/models/PasswordManager.cs
/models/SecretCodeGenerator.cs
/models/AccountManager.cs
This would allow you to have a consolidated url syntax. It would keep you from having many controllers with only 1 method. And it would keep you from having a lot of model type logic in the controllers.
www.mydomain.com/account/signup/
www.mydomain.com/account/confirm/
www.mydomain.com/account/resetpassword/
(with custom routes, you could even remove the /account/ part if you wish)
However, I might be tempted to create a custom controller to handle redeeming of secret codes. (redeemController) This way you could control access to much of the accountController to authorized/existing users only, whereas the redeem controller (depending on your design) may be open to anonymous for new customers.
Finally, having most of the logic in the model classes makes them much more test friendly.
i am just curious
when i will need to use a custom AccessDecisionManager
i need some use cases from your experience guys, if anyone have used it before, thanks.
The canonical example given in the Spring Security docs is for customizing voter tallies, like if a particular voter should be weighted more heavily than others.
You could also customize behavior based on, say, properties of the secured object passed in to the decide method, for example, based on existing business logic. (That could also be handled by a custom voter, or other means, but if it's generic it might be easier to put it in a decision manager.)
IMO it's relatively unusual to need extensive customization at this level, but others may have additional insight.
You also need a custom AcceessDecisionManager if you have complex object for a granted authority, spring default only supports string for that.