この問題の解決策は非常に簡単です。Jackson の一連のビュー クラスを作成しました。
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 {};
}
次に、以下を追加して、保護したい各エンティティのすべてのゲッター メソッドに注釈を付けました。
@JsonView(SecureViews.Authenticated.class)
public String getPhoneNumber() {
return phoneNumber;
}
上記のルールが意味することは、システム内で認証されたユーザーのみがユーザーの電話番号を表示できるということです。
または
@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;
}
今魔法のために。次のメソッドを拡張MappingJacksonJsonView
してオーバーライドします。
@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);
}
SpringsetObjectMapper
がMappingJacksonJsonView
.
私の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 に逆シリアル化する必要があるたびに、 renderMergedOutputModel メソッドが呼び出されます。ユーザーの ID がリクエストに含まれている場合は、それを保存します。次に、モデル マップをループして、各値が SecurePropertyInterface であるかどうか、および最大のアクセス許可レベルを取得しているかどうかを確認できます。
この戦略は、私の目的を適切に果たしているようです。ユーザーがユーザーのリストを要求すると、認証済みのプロパティのみが取得されますが、ユーザーが自分の詳細を要求すると、プライベート プロパティのみが取得されます。
このコードはさらに改善できると思いますが、複雑さを軽減するために多くの時間を費やしました。