四、 安全性
除了资源注入外,JSR 250和EJB 3.0还提供经由注解的元数据安全表示。javax.annotation.security包定义了五个注解-RunAs,RolesAllowed,PermitAll,DenyAll和RolesReferenced-所有这些都能应用到方法上来定义安全要求。例如,如果你想要声明上面列出的bookFlight方法仅能为具有"user"角色的调用者所执行,那么你可以用如下的安全约束来注解这个方法:
public class TravelAgencyServiceImpl implements ITravelAgencyService
{
@Resource(name = "flightDAO")
public IFlightDAO flightDAO;
@RolesAllowed("user")
public void bookTrip(long outboundFlightID, long returnFlightID, int seats)
throws InsufficientSeatsException
{
reserveSeats(outboundFlightID, seats);
reserveSeats(returnFlightID, seats);
}
}
这个注解将指出由容器来负责保证只有指定角色的调用者才能执行这个方法。因此现在我将展示另一个简单的方面-它将进一步加强在该应用程序上的安全约束:
@Aspect
public class SecurityAspect
{
@Around("execution(@javax.annotation.security.RolesAllowed * *.*(..))")
public Object aroundSecuredMethods(ProceedingJoinPoint thisJoinPoint)
throws Throwable
{
boolean callerAuthorized = false;
RolesAllowed rolesAllowed = rolesAllowedForJoinPoint(thisJoinPoint);
for (String role : rolesAllowed.value())
{
if (callerInRole(role))
{ callerAuthorized = true; }
}
if (callerAuthorized)
{ return thisJoinPoint.proceed(); }
else
{
throw new RuntimeException("Caller not authorized to perform specified function");
}
}
private RolesAllowed rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint)
{
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
return targetMethod.getAnnotation(RolesAllowed.class);
}
private boolean callerInRole(String role)
{ ... }
}
这个方面包含了所有方法的执行-通过核实该调用者是在注解中所指定的角色之一,用@RolesAllowed注解来注解并且保证调用者被授权调用该方法。当然你还能代之以任何你喜欢的算法来授权用户并且检索他/她的角色,例如JAAS或一个定制的解决方案。在本示例程序中,为方便起见,我选择代理到servlet容器。
