简体   繁体   中英

Spring security check if user has access to mentioned url

I have started using spring security, and after a lot of research I am not able to find an answer for:

If I explicitly want to check if user A have access to stuff B. I can check this with JSP tag support Spring Security - check if web url is secure / protected like

<sec:authorize url="stuff/B">

But what if I want to check the same thing in the controller(java class). I am not finding any spring function here to check if a login user has access to mentioned url( https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html )

Hint from the javadoc :

to use this tag there must also be an instance of WebInvocationPrivilegeEvaluator in your application context. If you are using the namespace, one will automatically be registered. This is an instance of DefaultWebInvocationPrivilegeEvaluator ,"

And in the javadoc of DefaultWebInvocationPrivilegeEvaluator , we can see a isAllowed method that should do the job:

// privilegeEvaluator is a WebInvocationPrivilegeEvaluator "autowired"
boolean allowed = privilegeEvaluator.isAllowed("/stuff/B", yourAuthentication);

Why not to use annotations like this:

@PreAuthorize("hasRole('ROLE_USER')")
public void create(Contact contact);

Annotations are standard way for Spring 3+

You are looking at the right place, the link you attached mentions what you need. Since you want access-control on your controller and check per user (not role) you can use the '@PreAuthorize' annotation with "hasPermission" expression or similar.

You could check here for expression-based access control and here for examples of custom security expression example in case you want to customize the solution.

1) First we need to know whether the user may enter the URL at all. This can be very easily achieved using WebInvocationPrivilegeEvaluator.

privilegeEvaluator.isAllowed(contextPath, url, "GET", currentUser);

2) Now we need to identifying whether the user may access the handler method

private boolean isAllowedByAnnotation(Authentication currentUser, HandlerMethod method) {
    PreInvocationAuthorizationAdvice advice = new ExpressionBasedPreInvocationAdvice();
    PreInvocationAuthorizationAdviceVoter voter = new PreInvocationAuthorizationAdviceVoter(advice);

    MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
    PrePostInvocationAttributeFactory factory = new ExpressionBasedAnnotationAttributeFactory(expressionHandler);
    PrePostAnnotationSecurityMetadataSource metadataSource = new PrePostAnnotationSecurityMetadataSource(factory);

    Class<?> controller = method.getBeanType();
    MethodInvocation mi = MethodInvocationUtils.createFromClass(controller, method.getMethod().getName());
    Collection<ConfigAttribute> attributes = metadataSource.getAttributes(method.getMethod(), controller);

    return PreInvocationAuthorizationAdviceVoter.ACCESS_GRANTED == voter.vote(currentUser, mi, attributes);
}

We can create a custom PermissionEvaluator and use

hasPermission(Authentication authentication, Object domainObject, Object permission).

  @Override
  protected MethodSecurityExpressionHandler createExpressionHandler() {
    final DefaultMethodSecurityExpressionHandler expressionHandler =
        new DefaultMethodSecurityExpressionHandler();
    expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
    return expressionHandler;
  }

 @Bean
  public aclServiceImpl aclService() {
    final AclServiceImpl mutableAclService = new AclServiceImpl 
        (authorizationStrategy(), grantingStrategy());
    return mutableAclService;
  }

AclServiceImpl is the implementation of MutableAclService

The most obviously useful annotation is @PreAuthorize which decides whether a method can actually be invoked or not. For example (from the"Contacts" sample application)

@PreAuthorize("hasRole('USER')")
public void create(Contact contact);

which means that access will only be allowed for users with the role "ROLE_USER ". Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role. But what about:

@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

Here we're actually using a method argument as part of the expression to decide whether the current user has the "admin"permission for the given contact. The built-in hasPermission() expression is linked into the Spring Security ACL module through the application context.

For More Detailed Explanation please refer this Link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM