问题描述
我想使用@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>
security.xml
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
}
}
然后在Web控制器中使用它:
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";
}
这篇关于具有hasPermission()的@PreAuthorize执行两次代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!