私は単純な一対多の関係で春のデータ休憩アプリケーションを持っています。Springデータを避ける方法コントローラ上でAccessDeniedExceptionが発生したときにHTTP 400を投げるRest
(1つの組織には、0人以上の従業員が含まれています)。どのようなセキュリティのないシナリオで
、私はこのような組織に従業員を追加することができます。 従業員のペイロードは、残りのコントローラにプッシュされcurl -v -H "Content-Type:application/json" -d '{"name":"name1","organization":"http://localhost:8080/api/organizations/1"}' http://localhost:8080/api/employee
、春データ残りは組織のURIに変換しますエンティティ、従業員にそれを接続し、すべてうまく動作します。
しかし、私は組織APIのセキュリティを開始し、認証されたユーザーには(ビジネスロジックに基づいて)組織を見ることができるようにしたいとします。
@RepositoryRestResource
public interface OrganizationController extends CrudRepository<Organization, Long> {
@PreAuthorize("@securityService.isAllowedToSeeTheOrganization(#id)")
Organization findOne(@P("id") Long id);
}
SecurityServiceは、ユーザーが自分のプロファイルに基づいて組織を取り出すことができているかどうかを判断するために、いくつかのビジネスロジックを実装しています:
@Service
public class SecurityService {
public boolean isAllowedToSeeOrganization(Long organizationId) {
return isAdmin() || belongsToOrganization(organizationId);
}
private boolean isAdmin() {
return SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(new SimpleGrantedAuthority(ADMIN.getRoleName()));
}
private boolean belongsToOrganization(Long organizationId) {
return organizationId == Long.parseLong(getUserDetails().get(ORGANIZATION_ID_FIELD).toString());
}
protected Map<String,Object> getUserDetails() {
JwtAuthentication jwtAuthentication = (JwtAuthentication) SecurityContextHolder.getContext().getAuthentication();
return jwtAuthentication.getJwtClaimsSet().getClaims();
}
}
このオフコースとしても、上記の呼び出しに影響を持つことになります組織のURIをエンティティに変換することができなくなります。ログに
{
"cause":{
"cause":{
"cause":null,
"message":"Access is denied"
},
"message":"Access is denied (through reference chain: com.example.Employee[\"organization\"])"
},
"message":"Could not read document: Access is denied (through reference chain: com.example.Employee[\"organization\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Access is denied (through reference chain: com.example.Employee[\"organization\"])"
}
:
しかし、代わりに禁断の403を投げるの、APIコールはHTTP 400(不正な要求)と、次のボディで失敗
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Access is denied (through reference chain: com.example.Employee["organization"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1599) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:359) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2922) ~[jackson-databind-2.8.5.jar:2.8.5]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:237) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
... 97 common frames omitted
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at com.sun.proxy.$Proxy156.findOne(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216) ~[spring-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.data.repository.support.ReflectionRepositoryInvoker.invoke(ReflectionRepositoryInvoker.java:265) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.repository.support.ReflectionRepositoryInvoker.invokeFindOne(ReflectionRepositoryInvoker.java:140) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.repository.support.CrudRepositoryInvoker.invokeFindOne(CrudRepositoryInvoker.java:91) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory$UnwrappingRepositoryInvoker.invokeFindOne(UnwrappingRepositoryInvokerFactory.java:130) ~[spring-data-rest-core-2.5.6.RELEASE.jar:na]
at org.springframework.data.rest.core.UriToEntityConverter.convert(UriToEntityConverter.java:123) ~[spring-data-rest-core-2.5.6.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$UriStringDeserializer.deserialize(PersistentEntityJackson2Module.java:516) ~[spring-data-rest-webmvc-2.5.6.RELEASE.jar:na]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:357) ~[jackson-databind-2.8.5.jar:2.8.5]
事実クライアントに内部情報が漏洩していると私には間違ったことがあるように思えます。
この場合、403 Forbiddenを返すか、このエラーメッセージをカスタマイズする方法があります。
どうすればいいですか?
securityService、employee、およびspringのセキュリティ設定のコードを共有できますか? JSONマッピングに何らかのエラーがあると思われるため、400がスローされます。 –
スタックトレース/セキュリティサービスの実装を追加しました。データレストUri/Entityコンバーターはリポジトリ呼び出しをトリガーします。認証オブジェクトはその呼び出しを実行できません(PreAuthorize)、AccessDeniedExceptionがスローされます。 AccessDeniedExceptionはスタックの上にプッシュされ、SpringはHTTP 400をクライアントにスローします。私はまだ400の代わりに403を期待しています。 – ddewaele