这个问题的解决方案非常简单。我创建了杰克逊一组视图类:
@JsonView(SecureViews.Authenticated.class)
public String getPhoneNumber() {
return phoneNumber;
}
什么上面的规则的意思是:
public class SecureViews {
public static class Public{};
public static class Authenticated extends Public{};
public static class User extends Authenticated{};
public static class Internal extends User {};
}
我然后通过添加以下带标注的所有每个实体的getter方法我想固定只有在系统内进行身份验证的用户才能查看用户的电话号码。
或者
@JsonView(SecureViews.User.class)
public List<Event> getEvents() {
return Collections.unmodifiableList(events);
}
然后我创建了一个接口,并实现在我所有的安全实体的接口:
public interface SecurePropertyInterface {
Class<?> getMaxPermissionLevel(Long userID);
}
这里是方法的实现:
public Class<?> getMaxPermissionLevel(Long userID) {
if (userID != null && userID == uid) {
return SecureViews.User.class;
}
if (SecurityUtils.getSubject().isAuthenticated()) {
return SecureViews.Authenticated.class;
}
return SecureViews.Public.class;
}
现在的魔法。扩展并覆盖下面的方法:
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Long userID = CTConversionUtils.convertToLong(request.getParameter("id"));
model = (Map<String, Object>) super.filterModel(model);
Class<?> viewClass = SecureViews.Public.class;
if(SecurityUtils.getSubject().isAuthenticated()) {
viewClass = SecureViews.Authenticated.class;
}
for (Entry<String, Object> modelEntry : model.entrySet()) {
if (modelEntry.getValue() instanceof SecurePropertyInterface) {
viewClass = ((SecurePropertyInterface)modelEntry.getValue()).getMaxPermissionLevel(userID);
}
}
objectMapper.viewWriter(viewClass).writeValue(getJsonGenerator(response), model);
}
您也可以覆盖setObjectMapper
方法来捕获objectMapper当春天设置您的。
我的Spring配置如下:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
p:order="1">
<property name="mediaTypes">
<map>
<entry key="json" value="*/*" />
</map>
</property>
<property name="defaultViews">
<list>
<bean
class="com.bytesizecreations.connecttext.json.SecureMappingJacksonJsonView">
<property name="objectMapper">
<bean
class="org.codehaus.jackson.map.ObjectMapper" />
</property>
</bean>
</list>
</property>
</bean>
那么,我们现在在这里?每次需要将响应反序列化为JSON时,都会调用renderedMergedOutputModel方法。如果用户的ID在请求中,我们将其存储。然后,我们可以遍历模型映射并检查每个值是否为SecurePropertyInterface,以及它是否获得其最大权限级别。
这个策略似乎正确地服务于我的目的。当用户请求用户列表时,他们只能获得已认证的属性,但当用户请求自己的详细信息时,他们只能获得其私有属性。
虽然我怀疑这个代码可以进一步改进,但是我花了太多的时间试图让它变得更简单。
你可以做'Class >',并取消原始类型警告。 – 2011-03-30 06:52:04
谢谢。我已经添加了它。 – 2011-03-30 15:45:42