有没有什么好方法可以根据Spring Security角色过滤JSON输出?我在找@JsonIgnore之类的东西,但要找role,比如@HasRole(“role_ADMIN”)。我应该如何实现这一点?
尽管可以编写自定义的JSON处理过滤器(例如基于JSON指针),但要做到这一点会有点复杂。
最简单的方法是创建自己的DTO并仅映射用户有权获取的那些属性。
你应该考虑使用rkonovalov/jfilter.特别是@DynamicFilterComponent
帮助很大.你可以在这篇DZone文章中看到一个很好的指南。
@DynamicFilterComponent
在这里解释。
我刚刚实现了您上面提到的要求。我的系统使用RestfulJersey 1.17
,Spring Security 3.0。7
,杰克逊1.9。2
。但是该解决方案与Jersey Restful API无关,您可以在任何其他类型的Servlet实现上使用它。
这是我的解决方案的全部5个步骤:
>
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonSpringView {
String springRoles();
}
然后一个注释内省器,它的大多数方法都应该返回null
,根据您的需要填充方法,以满足我刚才使用的isIgnorableField
的要求<代码>功能是我对GrantedAuthority接口的实现。这样地:
@Component
public class JsonSpringViewAnnotationIntrospector extends AnnotationIntrospector implements Versioned
{
// SOME METHODS HERE
@Override
public boolean isIgnorableField(AnnotatedField)
{
if(annotatedField.hasAnnotation(JsonSpringView.class))
{
JsonSpringView jsv = annotatedField.getAnnotation(JsonSpringView.class);
if(jsv.springRoles() != null)
{
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(principal != null && principal instanceof UserDetails)
{
UserDetails principalUserDetails = (UserDetails) principal;
Collection<? extends GrantedAuthority> authorities = principalUserDetails.getAuthorities();
List<String> requiredRoles = Arrays.asList(jsv.springRoles().split(","));
for(String requiredRole : requiredRoles)
{
Feature f = new Feature();
f.setName(requiredRole);
if(authorities.contains(f))
// if The Method Have @JsonSpringView Behind it, and Current User has The Required Permission(Feature, Right, ... . Anything You may Name It).
return false;
}
// if The Method Have @JsonSpringView Behind it, but the Current User doesn't have The required Permission(Feature, Right, ... . Anything You may Name It).
return true;
}
}
}
// if The Method Doesn't Have @JsonSpringView Behind it.
return false;
}
}
Jersey服务器有一个默认的ObjectMapper
,用于序列化/反序列化目的。如果您正在使用这样的系统,并且希望更改它的默认ObjectMapper,那么步骤3、4和5就是您的了,否则您可以阅读此步骤,您的工作就完成了。
@Provider
public class JsonSpringObjectMapperProvider implements ContextResolver<ObjectMapper>
{
ObjectMapper mapper;
public JsonSpringObjectMapperProvider()
{
mapper = new ObjectMapper();
AnnotationIntrospector one = new JsonSpringViewAnnotationIntrospector();
AnnotationIntrospector two = new JacksonAnnotationIntrospector();
AnnotationIntrospector three = AnnotationIntrospector.pair(one, two);
mapper.setAnnotationIntrospector(three);
}
@Override
public ObjectMapper getContext(Class<?> arg0) {
return this.mapper;
}
}
您应该扩展javax.ws.rs.core.Application
,并在W中提及您的类名eb.xml.我的是RestApplication。像这样:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestApplication extends Application
{
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(JsonSpringObjectMapperProvider.class);
return classes ;
}
}
这是最后一步。你应该在web.xml中提到你的应用程序类(从第4步开始):
<servlet>
<servlet-name>RestService</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.package</param-name>
<param-value>your_restful_resources_package_here</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<!-- THIS IS THE PART YOU SHOULD PPPAYYY ATTTTENTTTTION TO-->
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>your_package_name_here.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
从现在起,您只需要在任何想要的属性后面提到@JsonSpringView注释。这样地:
public class PersonDataTransferObject
{
private String name;
@JsonSpringView(springRoles="ADMIN, SUPERUSER") // Only Admins And Super Users Will See the person National Code in the automatically produced Json.
private String nationalCode;
}
对于那些从谷歌登陆这里的人,这里有一个类似的解决方案,它是SpringBoot1.4。
为每个角色定义接口,例如。
public class View {
public interface Anonymous {}
public interface Guest extends Anonymous {}
public interface Organizer extends Guest {}
public interface BusinessAdmin extends Organizer {}
public interface TechnicalAdmin extends BusinessAdmin {}
}
在实体中声明@JsonView
,例如。
@Entity
public class SomeEntity {
@JsonView(View.Anonymous.class)
String anonymousField;
@JsonView(View.BusinessAdmin.class)
String adminField;
}
并定义一个@ControlllerAdtions
来根据角色选择正确的JsonView
:
@ControllerAdvice
public class JsonViewConfiguration extends AbstractMappingJacksonResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return super.supports(returnType, converterType);
}
@Override
protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType,
MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
Class<?> viewClass = View.Anonymous.class;
if (SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().getAuthorities() != null) {
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
if (authorities.stream().anyMatch(o -> o.getAuthority().equals(Role.GUEST.getValue()))) {
viewClass = View.Guest.class;
}
if (authorities.stream().anyMatch(o -> o.getAuthority().equals(Role.ORGANIZER.getValue()))) {
viewClass = View.Organizer.class;
}
if (authorities.stream().anyMatch(o -> o.getAuthority().equals(Role.BUSINESS_ADMIN.getValue()))) {
viewClass = View.BusinessAdmin.class;
}
if (authorities.stream().anyMatch(o -> o.getAuthority().equals(Role.TECHNICAL_ADMIN.getValue()))) {
viewClass = View.TechnicalAdmin.class;
}
}
bodyContainer.setSerializationView(viewClass);
}
}
问题内容: 有什么好的方法可以根据Spring Security角色过滤JSON输出吗?我正在寻找类似@JsonIgnore的东西,但要寻找角色,例如@HasRole(“ ROLE_ADMIN”)。我应该如何实施呢? 问题答案: 有什么好的方法可以根据Spring Security角色过滤JSON输出吗?我正在寻找类似@JsonIgnore的东西,但要寻找角色,例如@HasRole(“ ROLE_
在 JAX-RS 应用程序中,必须根据已登录用户分配到的角色来筛选我的某些资源。我正在尝试使用安全注释(和)来实现此目的。 现在,每个人(匿名和登录用户)都可以并检索(每个id),但对于角色中的用户,我希望看到输出(此处序列化为JSON): 其他用户(无论是匿名用户还是非角色的其他用户)应该只看到: 我知道Jersey有实体过滤(以及基于安全角色进行过滤的实现)。 不幸的是,Liberty(基于A
使用spring webmvc和spring security web 3.2版,我希望根据用户角色(或用户是否经过身份验证)返回不同的视图,以便对于请求,角色匿名用户(或未经身份验证的用户)获得欢迎页面,角色用户用户获得主页。 我目前的做法是使用常规控制器: 然而,我并不喜欢它,因为我觉得这个重定向应该用SpringSecurity来完成(我错了吗?)。您知道使用Spring Security配
本文展示了如何根据不同的用户角色,在登录之后来重定向到不同的页面。 在 method-security项目的基础上,我们构建了一个role-base-login项目。 build.gradle 修改 build.gradle 文件,让我们的role-base-login项目成为一个新的项目。 修改内容也比较简单,修改项目名称及版本即可。 jar { baseName = 'role-bas
我正在使用Servlet过滤器来实施访问控制。扩展it以测试用户角色的最佳方式是什么?我能想出几种解决方案,但没有一种是优雅的。 编写角色测试并不难。但是如何将角色传递给给定url的过滤器? e、 在网络上。xml 谢谢
问题内容: 我正在寻找有关其他人如何设计此方法的意见。我将提供基于类(Django组)的视图。 例如,用户组将确定他或她将有权访问哪些视图/模板。我正在考虑也许在表中存储用于查看功能的路径,以确定用户的链接栏将由什么组成。过滤器规范也可以存储,以确定哪些行将填充这些模板。 医院护理单位就是一个很好的例子。一个单位的护士不必看整个医院的病人。他们只需要去看病人。同一部门的医生也只需要看望那些患者,但