mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-14 14:30:10 +00:00
Implemented custom serialization for UserImpl again. This should fix
deserialization of object cycles (UserImpl -> HashSet -> RoleImpl -> UserImpl) where uninitialized objects are inserted into a HashSet.
This commit is contained in:
1 parent
70b036826c
commit
aa16714fd5
3 files changed
+67
-38
No files matched your search
+17
-3
@@ -1,21 +1,35 @@
|
||||
package com.sap.sse.security.shared.dto;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.shared.WildcardPermission;
|
||||
import com.sap.sse.security.shared.impl.SecurityUserImpl;
|
||||
|
||||
public class StrippedUserDTO extends SecurityUserImpl<RoleDefinitionDTO, RoleDTO, StrippedUserGroupDTO> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private Set<RoleDTO> roles;
|
||||
|
||||
@Deprecated
|
||||
private StrippedUserDTO() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public StrippedUserDTO(String name, Iterable<RoleDTO> roles, Iterable<WildcardPermission> permissions) {
|
||||
super(name, roles, permissions);
|
||||
super(name, permissions);
|
||||
roles = new HashSet<>();
|
||||
Util.addAll(roles, this.getRolesInternal());
|
||||
}
|
||||
|
||||
public StrippedUserDTO(String name) {
|
||||
super(name);
|
||||
this(name, Collections.<RoleDTO>emptySet(), Collections.<WildcardPermission>emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<RoleDTO> getRolesInternal() {
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
+7
-35
@@ -5,7 +5,6 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.shared.AbstractRole;
|
||||
import com.sap.sse.security.shared.RoleDefinition;
|
||||
import com.sap.sse.security.shared.SecurityUser;
|
||||
@@ -18,51 +17,24 @@ public abstract class SecurityUserImpl<RD extends RoleDefinition, R extends Abst
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Roles can refer back to this user object, e.g., for the user qualification, or during the tenant
|
||||
* qualification if this user belongs to the tenant for which the role is qualified. Therefore, this
|
||||
* set has to be transient, and the {@link #roleListForSerialization} field takes over the serialization
|
||||
* which is resolved by {@link #readResolve}.
|
||||
*
|
||||
* @see #writeObject
|
||||
* @see #readResolve
|
||||
*/
|
||||
private Set<R> roles;
|
||||
|
||||
// private List<R> roleListForSerialization;
|
||||
|
||||
private Set<WildcardPermission> permissions;
|
||||
|
||||
/**
|
||||
* Creates a user with empty permission set and empty role set
|
||||
*/
|
||||
public SecurityUserImpl(String name) {
|
||||
this(name, new HashSet<R>(), new HashSet<WildcardPermission>());
|
||||
this(name, new HashSet<WildcardPermission>());
|
||||
}
|
||||
|
||||
public SecurityUserImpl(String name, Iterable<R> roles, Iterable<WildcardPermission> permissions) {
|
||||
public SecurityUserImpl(String name, Iterable<WildcardPermission> permissions) {
|
||||
this.name = name;
|
||||
this.roles = new HashSet<>();
|
||||
Util.addAll(roles, this.roles);
|
||||
this.permissions = new HashSet<>();
|
||||
for (WildcardPermission permission : permissions) {
|
||||
this.permissions.add(permission);
|
||||
}
|
||||
}
|
||||
|
||||
// @GwtIncompatible
|
||||
// private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
// roleListForSerialization = new ArrayList<>(roles);
|
||||
// oos.defaultWriteObject();
|
||||
// roleListForSerialization = null;
|
||||
// }
|
||||
//
|
||||
// @GwtIncompatible
|
||||
// protected Object readResolve() {
|
||||
// roles = new HashSet<>(roleListForSerialization);
|
||||
// roleListForSerialization = null;
|
||||
// return this;
|
||||
// }
|
||||
protected abstract Set<R> getRolesInternal();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -76,12 +48,12 @@ public abstract class SecurityUserImpl<RD extends RoleDefinition, R extends Abst
|
||||
|
||||
@Override
|
||||
public Iterable<R> getRoles() {
|
||||
return roles;
|
||||
return getRolesInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRole(R role) {
|
||||
return roles.contains(role);
|
||||
return getRolesInternal().contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,11 +62,11 @@ public abstract class SecurityUserImpl<RD extends RoleDefinition, R extends Abst
|
||||
}
|
||||
|
||||
public void addRole(R role) {
|
||||
roles.add(role);
|
||||
getRolesInternal().add(role);
|
||||
}
|
||||
|
||||
public void removeRole(R role) {
|
||||
roles.remove(role);
|
||||
getRolesInternal().remove(role);
|
||||
}
|
||||
|
||||
public void addPermission(WildcardPermission permission) {
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package com.sap.sse.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.shiro.crypto.hash.Sha256Hash;
|
||||
|
||||
@@ -69,6 +75,19 @@ public class UserImpl extends SecurityUserImpl<RoleDefinition, Role, UserGroup>
|
||||
private final Map<AccountType, Account> accounts;
|
||||
|
||||
private transient UserGroupProvider userGroupProvider;
|
||||
|
||||
/**
|
||||
* Roles can refer back to this user object, e.g., for the user qualification, or during the tenant
|
||||
* qualification if this user belongs to the tenant for which the role is qualified. Therefore, this
|
||||
* set has to be transient, and the {@link #roleListForSerialization} field takes over the serialization
|
||||
* which is resolved by {@link #readResolve}.
|
||||
*
|
||||
* @see #writeObject
|
||||
* @see #readResolve
|
||||
*/
|
||||
private transient Set<Role> roles;
|
||||
|
||||
private List<Role> roleListForSerialization;
|
||||
|
||||
public UserImpl(String name, String email, Map<String, UserGroup> defaultTenantForServer,
|
||||
UserGroupProvider userGroupProvider, Account... accounts) {
|
||||
@@ -99,6 +118,30 @@ public class UserImpl extends SecurityUserImpl<RoleDefinition, Role, UserGroup>
|
||||
for (Account a : accounts) {
|
||||
this.accounts.put(a.getAccountType(), a);
|
||||
}
|
||||
roles = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Role> getRolesInternal() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
oos.writeObject(new ArrayList<>(roles));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readObject(java.io.ObjectInputStream ois)
|
||||
throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
roleListForSerialization = (List<Role>) ois.readObject();
|
||||
}
|
||||
|
||||
protected Object readResolve() {
|
||||
roles = new HashSet<>(roleListForSerialization);
|
||||
roleListForSerialization = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user