@PreAuthorize with hasPermission() 执行代码两次 [英] @PreAuthorize with hasPermission() executes code twice

查看:122
本文介绍了@PreAuthorize with hasPermission() 执行代码两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 @PreAuthorize Spring 注释来控制我的应用程序中的访问.

I want to use @PreAuthorize Spring annotation to controll access in my application.

问题是,我有很多条件不取决于请求参数,而是取决于数据库实体.

The problem is, that I have a lot of conditions depends not on the request parameters, but on the database entities.

概述:

我有一个 Route 实体,它有 User owner 字段.仅当您是所有者时才能删除 Route.

I have an Route entity, that has User owner field. You can remove the Route only if you are an owner.

我已经编写了我的控制器方法:

I have written my controller method:

@RequestMapping(value = "/route/remove/{id}", method = RequestMethod.GET)
@PreAuthorize("hasPermission(#id, 'RouteRemove')")
  public String removeRoute(@PathVariable("id") Integer id, ModelMap model) {

  Route route = routeBO.getById(id);

  if(null == route)
    return "forward:/errors/404";

  // ... remove route here.
  // routeBO.remove(id);
}

我的RouteRemove权限定义为:

@Component
public class RouteRemovePermission implements Permission {

    @Autowired
    private RouteBO routeBO;

    @Override
    public boolean isAllowed(Authentication authentication, Object targetDomainObject) {
        if(!(targetDomainObject instanceof Integer))
            return false;

        Route route = routeBO.getById((Integer) targetDomainObject);

        if(route == null)
            return false;

        User user = AthenticationUtil.getUser();

        return null != user && user.equals(route.getOwner());
    }

}

如您所见,我必须对 routeBO.getById() 求值两次.

As you can see, I have to evaluate routeBO.getById() twice.

问题:

是否可以只计算一次此代码?

is it possible to evaluate this code only once?

当然我试过了:

@RequestMapping(value = "/route/remove/{id}", method = RequestMethod.GET)
public String removeRoute(@PathVariable("id") Integer id, ModelMap model) {

Route route = routeBO.getById(id);

if(null == route)
  return "forward:/errors/404";

return removeRoute(route, model);
}

@PreAuthorize("hasPermission(#id, 'RouteRemove')")
public String removeRoute(Route id, ModelMap model) {

    return "route/display";
}

但是在removeRoute(Route id, ModelMap model)之前没有调用权限方法.也许我的配置不正确?

but there no invocation of permission method before removeRoute(Route id, ModelMap model). Maybe I have incorrect configuration?

mvc-dispatcher-servlet.xml

mvc-dispatcher-servlet.xml

<sec:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
  <sec:expression-handler ref="expressionHandler"/>
</sec:global-method-security>

安全性.xml

<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
</beans:bean>

<beans:bean id="permissionEvaluator" class="pl.wsiadamy.common.security.BasePermissionEvaluator">
  <beans:constructor-arg index="0">
        <beans:map key-type="java.lang.String"
             value-type="pl.wsiadamy.common.security.Permission">
            <beans:entry key="RouteView" value-ref="routeViewPermission" />
            <beans:entry key="RouteRemove" value-ref="routeRemovePermission" />
        </beans:map>
    </beans:constructor-arg>
</beans:bean>
<beans:bean id="routeViewPermission" class="pl.wsiadamy.common.security.permission.RouteViewPermission" />
<beans:bean id="routeRemovePermission" class="pl.wsiadamy.common.security.permission.RouteRemovePermission" />

推荐答案

我建议您将带有安全注释的 removeRoute 方法拆分为单独的服务类,例如:

I suggest you break out your security-annotated removeRoute method to a separate service class, like:

@Service
public class RouteService {
    @PreAuthorize("hasPermission(#route, 'RouteRemove')")
    public void removeRoute(Route route) {
        // remove route here
    }
}

然后你在你的网络控制器中使用它:

Then you use it in your web controller:

@Autowired RouteService routeService;

@RequestMapping(value = "/route/remove/{id}", method = RequestMethod.GET)
public String removeRoute(@PathVariable("id") Integer id, ModelMap model) {
    Route route = routeBO.getById(id);
    if(null == route)
        return "forward:/errors/404";
    routeService.removeRoute(route);
    return "route/display";
}

这篇关于@PreAuthorize with hasPermission() 执行代码两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆