Consider some basic authorization framework with Users and Groups where access to methods should be guarded by checks which make sure that the user or the group have the necessary PriviledgeLevel to execute the method and fails otherwise.
What I imagine is something like this:
#AccessCheck(PriviledgeLevel.ADMINISTRATOR)
public static void secureMethod(){ ... }
Where the code checking basically does
if(currentUser.getPriviledgeLevel >= PriviledgeLevel.ADMINISTRATOR ||
currentUser.getGroup.priviledgeLevel >= PriviledgeLevel.ADMINISTRATOR)
// Allow access
else
// Deny access
Would it be possible to implement it this way?
I did a bit of research which points to some existing things based on AspectJ, mostly on the Security Annotation Framework (SAF) and on Spring Security.
I'm a bit concerned because SAF doesn't seem very active anymore and the documentation isn't that great.
I'm not sure about Spring Security but it seems to be more focused on security problems in web-related topics.
The Java Authentication and Authorization Service seems to be related, but doesn't use the annotation approach.
Does it make sense trying to define these security requirements with this declarative approach?
Is there another library/framework I'm missing, which already implements what I want or some techonology which would be relevant here?
Or is there a completely different solution (like implementing my own ClassLoader, ...) which is superior to what I imagine (in terms of conciseness and readability for the library user)?
I think AspectJ will do what you want it to do. We have a whole bunch of methods which you need certain access rights for and we've created an AspectJ aspect which will check that and error out if the user does not have those permissions.
As a plus, because AspectJ is "woven" into the classes at compile time it cannot be disabled by configuration.
We also use Spring Security, it is possible to use both in harmony!
You could do this fairly trivially yourself by using dynamic proxies.
public interface MyInterface {
#AccessCheck(Privilege.ADMIN)
public void doSomething();
}
The proxy would be created on the class that implements your interface and you would annotate your interface with your custom annotation.
MyInterface aInterface = (MyInterface) java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
.getClassLoader(), obj.getClass().getInterfaces(),
new YourProxy(new Implementation());
In the invoke() method of your proxy, you can check if your method has the annotation and throw a SecurityException if the privileges are not met.
public YourProxy implements InvocationHandler {
....
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ( method.isAnnotationPresent(AccessCheck.class) {
....// do access check here and throw SecurityException()
}
}
With Spring Security, you just have to add:
#Secured("ADMINISTRATOR")
public static void secureMethod(){ ... }
And configure it properly, by:
use JdbcDaoImpl as your UserDetailsService
enable group support
customize the queries (if you are using database credential storage)
If you are not using database credential storage, just configure your preferred UserDetailsService to add both user and group credentials to the authorities of the generated UserDetails.
Of couse, it is hard to understand it without checking the concepts at the documentation, but method level access checks is perfectly possible with spring security and it's my prefered technology for it.
In Spring Security, as the docs state, both #Secured and #PreAuthorize can be used at method level.
To enable #PreAuthorize (if you haven't already...), you need to put <global-method-security pre-post-annotations="enabled" />
in your configuration XML;
For #Secured use <global-method-security secured-annotations="enabled" />.
For more details, refer to this article.
Related
Using Spring Security 5.2.X (latest currently), I need to prevent the access to a third party role to all methods but one in a SOAP service. In other words, I need that particular role to have access only to one particular method among all of the availables in the service.
Normally, a usual method level securization consists of annotation with #Secure("MY_ROLE"). This makes the method only to be accessible for that role.
Is it possible to tell Spring Security Core to do the opposite. I.e, configure it in a way that certain user only has access to the secured method.
Of course, the workaround could be:
// Method accessible by anyone but third party role
#Secured({"GOOD_ROLE1", "GOOD_ROLE2", "GOOD_ROLE3"})
public void methodAccessibleByAnyoneButThirdPartyRole(){
}
// Method accessible by anyone, including third party role
#Secured({"GOOD_ROLE1", "GOOD_ROLE2", "GOOD_ROLE3", "THIRD_PARTY_ROLE"})
public void methodAccessibleByAnyone(){
}
Other workaround would consist of just creating a new service only with the method to be restricted.
But is there any annotation option to get the same straightaway? Something like #PreAuthorize("!hasRole('THIRD_PARTY_ROLE')") or similar?
According to Spring Security doc you can use any Spring Expression Language (SpEL) in #PreAuthorize
Any Spring-EL functionality is available within the expression, so you
can also access properties on the arguments. For example, if you
wanted a particular method to only allow access to a user whose
username matched that of the contact, you could write
#PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact);
So you can use:
#PreAuthorize("!hasRole('THIRD_PARTY_ROLE')")
Also as more readable variant:
#PreAuthorize("not hasRole('THIRD_PARTY_ROLE')")
How to securing my Java page programatically using Spring
#Secured({"ROLE_USER", "ROLE_ADMIN"})
public class SecretClass extends BasePage {
// do work
}
But I want to do it programatically, get role from db first and put it.
public class SecretClass extends BasePage {
// Something like:
// String role = userManager.getRole();
// #Secured({"ROLE_USER", role})
#InjectService("UserManager")
private UserManager userManager;
}
But, I know you can't do like that with #Secured, so is there any way to do what I want by code? For securing whole page, not particular method.
read about spring security it will give u the required features which you want for your application more secured. https://projects.spring.io/spring-security/
I would prefer using the framework and not implementing (and testing) your own code especially in security context.
But if you really need to implement your own logic, you should take a look at #PreAuthorize . #Secured is an old annotation and kind of deprecated since #PreAuthorize can do much more and uses the spring expression language.
In our Project we used #PreAuthorize(hasPermission(...)) and implemented our own logic within hasPermission(). But this might be an overkill for you, since #PreAuthorize can already do a lot!
Take a look at the documentation.
I have a Spring web application which uses Spring SAML and Spring Security to manage the login process.
Now I need to do some tasks after the correct login occurs. In particular I have to store some data in the SecurityContext.getContext() object.
I have never worked with Spring Security/SAML and I don't know how it manages the return from the IdP.
Is there any place in the code where usually you can put your code after the login process ends correctly?
I mean, I know where the redirect page is set but I cannot put my custom code in the Controller of this redirect page because that page is accessed more than one time, and I need to run my custom code only once at login time.
The best approach is to implement interface SAMLUserDetailsService, which will automatically store object you return from its loadUserBySAML method in the Authentication object which you can later query from the SecurityContext.getContext(). The interface is called once after each authentication. See the manual for details and examples.
The other possibility is AuthenticationSuccessHandler. The login process calls method onAuthenticationSuccess which has access to the Authentication object, which will be stored in the SecurityContext.getContext().
Simply create your own class which implements interface AuthenticationSuccessHandler (you can also extend some of the existing classes, such as SimpleUrlAuthenticationSuccessHandler or AbstractAuthenticationTargetUrlRequestHandler). Then plug your implementation to the securityContext.xml by changing class in the existing successRedirectHandler bean.
The problem is, that the Authentication object tends to be immutable - so the first way might be better.
You can use AuthenticationSuccessEvent. Just register a bean that implements ApplicationListener.
#Component
public class SomeSpringBean implements
ApplicationListener<AuthenticationSuccessEvent> {
public onApplicationEvent(AuthenticationSuccessEvent event) {
String userName = ((UserDetails) event.getAuthentication().
//do stuff
}
}
And you need to register AuthenticationEventPublisher.
Take a look here: https://gist.github.com/msarhan/10834401
If you use custom authentication provider, you can also plug whatever you want there.
Are you using Spring's Java configs?
If so, then you probably have a class that overrides WebSecurityConfigurerAdapter in your project. Extending this class gives you access to override the method configure(HttpSecurity http).
You can use that provided HttpSecurity builder object to configure a lot of things, one of which is the authentication success handler. More or less, you can create a simple that class that implements AuthenticationSuccessHandler (Spring has a few classes already built for extension to make this easy), and you can call http.successHandler(yourSuccessHandler) to register it with Spring Security.
Implementing that interface gives you the hook to put custom code into the onAuthenticationSuccess( ... ) method. I think they have one for failures as well.
I want to see if it is possible to use annotations to evaulate if a user is logged in or not.
Example
#AuthRequired
public String myProtectedArea() {
return View("view/protectedArea"); // If user is NOT authenticated, return "view/login"
}
As per your edit:
Check this SO Post:
Scanning Java annotations at runtime
I'd still recommend using Spring Security for this, it's tested and secure:
#PreAuthorize("hasRole('ROLE_USER')")
public String myProtectedArea() {
return View("view/protectedArea");
}
The annotation will check if the user is logged in and has the required credentials.
Another way with Spring Security is to intercept the URL pattern by setting this inside a spring.security-settings.xml:
<intercept-url pattern="/view/protectedArea/*" access="hasRole('ROLE_USER')" />
I'd recommend using both to maximize security.
In the security settings file you can then tell spring security where to redirect the user to login. If the user is already logged in, you can redirect him to yet another page:
<form-login login-page="/view/login.xhtml" default-target-url="/view/protectedArea/home.xhtml"
authentication-failure-url="/view/login.xhtml" />
It's a tested framework and thus secure and versatile. However it requires a bit of setting up if you want more than the standard behaviour.
The annotation doesn't check if the user is logged in or not--annotations are metadata on classes/methods. Something must still make use of the annotation.
Something in your code checks to see if the method is annotated with #AuthRequired, if it is, checks if logged in, then executes the method based on that.
For example, a web app might look for the annotation in a filter, base servlet, interceptor, etc. and decide whether or not the request process should continue.
Depending upon what type of application you are creating there are a number of options available to you for defining authentication levels for specific methods.
I would most likely recommend to you Spring Security for such a task.
Something like the below example would be the end result after configuration using Spring Security.
#Secured( {"USER_ROLE"} )
public String getSecretData() {
return "SECRET! SHHH!";
}
Then only users verified by Spring Security to have the role you provide to the annotation will have authorization to call the method.
There are a couple other annotation options in Spring Security you can utilize such as #PreAuthorize.
Instead of re-inventing the wheel, have a look at JAAS:
http://docs.oracle.com/javaee/6/tutorial/doc/bncbx.html#bncca
http://docs.oracle.com/javaee/6/tutorial/doc/bncas.html
http://docs.oracle.com/javaee/6/tutorial/doc/gijrp.html
http://docs.oracle.com/javaee/6/api/javax/annotation/security/package-summary.html
I like to add an user authentification to my REST webservice (Guice + Jersey).
I first wanted to solve the authentification with the Google Guice method interceptions. For example:
#Path("user")
public class User {
#OnlyAdmin
#Post
public void addUser(String apiKey) {
}
}
But unfortunately Guice only support AOP for classes with a no-argument constructors.
Is it generally a good idea to use AOP for user authentification?
Are there other frameworks to build an user authentification?
Edit: Framework is maybe the wrong term. I'm only looking for a way to inject some code in every annotated method and this code should check the parameters of the method
The only important point for AOP to work in your case is that your classes get created by Guice.
If you have constructors with arguments, ensure that they are injectable (directly or with assisted injection).
It wouldn't be AOP but you could inject a current user role bound to the request scope wherever the user needed to be checked and use either method intercepts or explicit logic to check that the right user class is performing some action.