Spring Security ロールに基づいて JSON 出力をフィルタリングする良い方法はありますか? @JsonIgnore のようなものを探していますが、@HasRole("ROLE_ADMIN") のようなロールを探しています。これをどのように実装すればよいですか?
3 に答える
更新: 新しい回答
rkonovalov/jfilter の使用を検討する必要があります。特に@DynamicFilterComponent
大いに役立ちます。このDZone の記事で良いガイドを見ることができます。
@DynamicFilterComponent
ここで説明します。
古い答え
上記の要件を実装しました。私のシステムは Restful Jersey 1.17
、Spring Security 3.0.7
、を使用していJackson 1.9.2
ます。ただし、ソリューションは Jersey Restful API とは関係なく、他の種類のサーブレット実装で使用できます。
これは、私のソリューションの 5 つのステップ全体です。
まず、次のように、目的に合わせて Annotation クラスを作成する必要があります。
JsonSpringView.java
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface JsonSpringView { String springRoles(); }
次に、Annotation Introspector、そのほとんどのメソッドが返さ
null
れ、必要に応じてメソッドを入力します。使用したばかりの要件に対応しますisIgnorableField
。Feature
GrantedAuthority インターフェイスの私の実装です。このような:JsonSpringViewAnnotationIntrospector.java
@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 があなたのものです。JsonSpringObjectMapperProvider.java
@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
Web.xml でクラス名を拡張して言及する必要があります。私のはRestApplication.Likeです:RestApplication.java
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 で Application クラス (ステップ 4 から) に言及する必要があります。
私のweb.xmlの一部
<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 アノテーションに言及するだけです。このような:
PersonDataTransferObject.java
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;
}