You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2017/06/29 05:48:44 UTC
[37/50] kylin git commit: minor,
remove refine user cache in spring security
minor, remove refine user cache in spring security
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/3280172b
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/3280172b
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/3280172b
Branch: refs/heads/master
Commit: 3280172b737f85479eb3432fa12c267b477674fd
Parents: 22d8fae
Author: Hongbin Ma <ma...@apache.org>
Authored: Fri Jun 23 19:08:41 2017 +0800
Committer: liyang-gmt8 <li...@apache.org>
Committed: Fri Jun 23 20:26:46 2017 +0800
----------------------------------------------------------------------
.../apache/kylin/common/KylinConfigBase.java | 10 ++-
.../security/KylinAuthenticationProvider.java | 91 ++++++++++++--------
.../apache/kylin/rest/security/ManagedUser.java | 78 ++++++++---------
.../apache/kylin/rest/service/UserService.java | 10 +++
server/src/main/resources/ehcache-test.xml | 9 +-
server/src/main/resources/ehcache.xml | 9 +-
6 files changed, 111 insertions(+), 96 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
----------------------------------------------------------------------
diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
index 2ccf3cf..ecd5261 100644
--- a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
+++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
@@ -502,7 +502,7 @@ abstract public class KylinConfigBase implements Serializable {
public Integer getSchedulerPollIntervalSecond() {
return Integer.parseInt(getOptional("kylin.job.scheduler.poll-interval-second", "30"));
}
-
+
public Integer getErrorRecordThreshold() {
return Integer.parseInt(getOptional("kylin.job.error-record-threshold", "0"));
}
@@ -1073,6 +1073,14 @@ abstract public class KylinConfigBase implements Serializable {
return getOptionalIntArray("kylin.server.query-metrics-percentiles-intervals", dft);
}
+ public int getServerUserCacheExpireSeconds() {
+ return Integer.valueOf(this.getOptional("kylin.server.auth-user-cache.expire-seconds", "300"));
+ }
+
+ public int getServerUserCacheMaxEntries() {
+ return Integer.valueOf(this.getOptional("kylin.server.auth-user-cache.max-entries", "100"));
+ }
+
// ============================================================================
// WEB
// ============================================================================
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
index 7322b84..dd9cbad 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
@@ -18,7 +18,10 @@
package org.apache.kylin.rest.security;
-import org.apache.kylin.common.util.ByteArray;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.rest.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,13 +35,12 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-
/**
* A wrapper class for the authentication provider; Will do something more for Kylin.
*/
@@ -46,13 +48,21 @@ public class KylinAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = LoggerFactory.getLogger(KylinAuthenticationProvider.class);
+ private final static com.google.common.cache.Cache<String, Authentication> userCache = CacheBuilder.newBuilder()
+ .maximumSize(KylinConfig.getInstanceFromEnv().getServerUserCacheMaxEntries())
+ .expireAfterWrite(KylinConfig.getInstanceFromEnv().getServerUserCacheExpireSeconds(), TimeUnit.SECONDS)
+ .removalListener(new RemovalListener<String, Authentication>() {
+ @Override
+ public void onRemoval(RemovalNotification<String, Authentication> notification) {
+ KylinAuthenticationProvider.logger.debug("User cache {} is removed due to {}",
+ notification.getKey(), notification.getCause());
+ }
+ }).build();
+
@Autowired
@Qualifier("userService")
UserService userService;
- @Autowired
- private CacheManager cacheManager;
-
//Embedded authentication provider
private AuthenticationProvider authenticationProvider;
@@ -67,48 +77,53 @@ public class KylinAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- Authentication authed = null;
- Cache userCache = cacheManager.getCache("UserCache");
+
byte[] hashKey = hf.hashString(authentication.getName() + authentication.getCredentials()).asBytes();
- ByteArray userKey = new ByteArray(hashKey);
+ String userKey = Arrays.toString(hashKey);
+
+ if (userService.isEvictCacheFlag()) {
+ userCache.invalidateAll();
+ userService.setEvictCacheFlag(false);
+ }
+ Authentication authed = userCache.getIfPresent(userKey);
- Element authedUser = userCache.get(userKey);
- if (null != authedUser) {
- authed = (Authentication) authedUser.getObjectValue();
+ if (null != authed) {
SecurityContextHolder.getContext().setAuthentication(authed);
} else {
try {
authed = authenticationProvider.authenticate(authentication);
- userCache.put(new Element(userKey, authed));
+
+ ManagedUser user;
+
+ if (authed.getDetails() == null) {
+ //authed.setAuthenticated(false);
+ throw new UsernameNotFoundException(
+ "User not found in LDAP, check whether he/she has been added to the groups.");
+ }
+
+ if (authed.getDetails() instanceof UserDetails) {
+ UserDetails details = (UserDetails) authed.getDetails();
+ user = new ManagedUser(details.getUsername(), details.getPassword(), false,
+ details.getAuthorities());
+ } else {
+ user = new ManagedUser(authentication.getName(), "skippped-ldap", false, authed.getAuthorities());
+ }
+ Assert.notNull(user, "The UserDetail is null.");
+
+ logger.debug("User {} authorities : {}", user.getUsername(), user.getAuthorities());
+ if (!userService.userExists(user.getUsername())) {
+ userService.createUser(user);
+ } else {
+ userService.updateUser(user);
+ }
+
+ userCache.put(userKey, authed);
} catch (AuthenticationException e) {
logger.error("Failed to auth user: " + authentication.getName(), e);
throw e;
}
logger.debug("Authenticated user " + authed.toString());
-
- ManagedUser user;
-
- if (authed.getDetails() == null) {
- //authed.setAuthenticated(false);
- throw new UsernameNotFoundException(
- "User not found in LDAP, check whether he/she has been added to the groups.");
- }
-
- if (authed.getDetails() instanceof UserDetails) {
- UserDetails details = (UserDetails) authed.getDetails();
- user = new ManagedUser(details.getUsername(), details.getPassword(), false, details.getAuthorities());
- } else {
- user = new ManagedUser(authentication.getName(), "skippped-ldap", false, authed.getAuthorities());
- }
- Assert.notNull(user, "The UserDetail is null.");
-
- logger.debug("User authorities :" + user.getAuthorities());
- if (!userService.userExists(user.getUsername())) {
- userService.createUser(user);
- } else {
- userService.updateUser(user);
- }
}
return authed;
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/server-base/src/main/java/org/apache/kylin/rest/security/ManagedUser.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/ManagedUser.java b/server-base/src/main/java/org/apache/kylin/rest/security/ManagedUser.java
index 4805d5c..280339e 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/security/ManagedUser.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/ManagedUser.java
@@ -22,8 +22,6 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import javax.annotation.Nullable;
-
import org.apache.kylin.common.persistence.RootPersistentEntity;
import org.apache.kylin.rest.service.UserGrantedAuthority;
import org.springframework.security.core.GrantedAuthority;
@@ -31,8 +29,6 @@ import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
@SuppressWarnings("serial")
@@ -44,7 +40,7 @@ public class ManagedUser extends RootPersistentEntity implements UserDetails {
@JsonProperty
private String password;
@JsonProperty
- private List<String> authorities = Lists.newArrayList();
+ private List<UserGrantedAuthority> authorities = Lists.newArrayList();
@JsonProperty
private boolean disabled = false;
@JsonProperty
@@ -56,24 +52,40 @@ public class ManagedUser extends RootPersistentEntity implements UserDetails {
@JsonProperty
private int wrongTime = 0;
- private Boolean legacyCatered = false;
//DISABLED_ROLE is a ancient way to represent disabled user
//now we no longer support such way, however legacy metadata may still contain it
private static final String DISABLED_ROLE = "--disabled--";
- //this is computed
- private List<UserGrantedAuthority> grantedAuthorities = null;
-
public ManagedUser() {
}
- public ManagedUser(String username, String password, Boolean defaultPassword, String... authorities) {
+ public ManagedUser(@JsonProperty String username, @JsonProperty String password,
+ @JsonProperty List<UserGrantedAuthority> authorities, @JsonProperty boolean disabled,
+ @JsonProperty boolean defaultPassword, @JsonProperty boolean locked, @JsonProperty long lockedTime,
+ @JsonProperty int wrongTime) {
+ this.username = username;
+ this.password = password;
+ this.authorities = authorities;
+ this.disabled = disabled;
+ this.defaultPassword = defaultPassword;
+ this.locked = locked;
+ this.lockedTime = lockedTime;
+ this.wrongTime = wrongTime;
+
+ caterLegacy();
+ }
+
+ public ManagedUser(String username, String password, Boolean defaultPassword, String... authoritiesStr) {
this.username = username;
this.password = password;
this.setDefaultPassword(defaultPassword);
- this.authorities = Lists.newArrayList(authorities);
- this.grantedAuthorities = null;
+ this.authorities = Lists.newArrayList();
+ for (String a : authoritiesStr) {
+ authorities.add(new UserGrantedAuthority(a));
+ }
+
+ caterLegacy();
}
public ManagedUser(String username, String password, Boolean defaultPassword,
@@ -83,6 +95,8 @@ public class ManagedUser extends RootPersistentEntity implements UserDetails {
this.setDefaultPassword(defaultPassword);
this.setGrantedAuthorities(grantedAuthorities);
+
+ caterLegacy();
}
public String getUsername() {
@@ -102,45 +116,27 @@ public class ManagedUser extends RootPersistentEntity implements UserDetails {
}
private void caterLegacy() {
- if (!legacyCatered) {
- synchronized (legacyCatered) {
- Iterator<String> iterator = authorities.iterator();
- while (iterator.hasNext()) {
- if (DISABLED_ROLE.equals(iterator.next())) {
- iterator.remove();
- this.disabled = true;
- }
- }
- legacyCatered = true;
+ Iterator<UserGrantedAuthority> iterator = authorities.iterator();
+ while (iterator.hasNext()) {
+ if (DISABLED_ROLE.equals(iterator.next().getAuthority())) {
+ iterator.remove();
+ this.disabled = true;
}
}
}
public List<UserGrantedAuthority> getAuthorities() {
- caterLegacy();
- if (grantedAuthorities == null) {
- grantedAuthorities = Lists.newArrayList();
- for (String a : authorities) {
- this.grantedAuthorities.add(new UserGrantedAuthority(a));
- }
- }
- return grantedAuthorities;
+ return this.authorities;
}
public void setGrantedAuthorities(Collection<? extends GrantedAuthority> grantedAuthorities) {
- this.authorities = Lists
- .newArrayList(Collections2.transform(grantedAuthorities, new Function<GrantedAuthority, String>() {
- @Nullable
- @Override
- public String apply(@Nullable GrantedAuthority input) {
- return input.getAuthority();
- }
- }));
- this.grantedAuthorities = null;
+ this.authorities = Lists.newArrayList();
+ for (GrantedAuthority grantedAuthority : grantedAuthorities) {
+ this.authorities.add(new UserGrantedAuthority(grantedAuthority.getAuthority()));
+ }
}
public boolean isDisabled() {
- caterLegacy();
return disabled;
}
@@ -230,6 +226,6 @@ public class ManagedUser extends RootPersistentEntity implements UserDetails {
@Override
public String toString() {
- return "KapManagedUser [username=" + username + ", authorities=" + grantedAuthorities + "]";
+ return "ManagedUser [username=" + username + ", authorities=" + authorities + "]";
}
}
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java b/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
index 504c035..6682c03 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
@@ -54,6 +54,16 @@ public class UserService implements UserDetailsManager {
public static final Serializer<ManagedUser> SERIALIZER = new JsonSerializer<>(ManagedUser.class);
protected ResourceStore aclStore;
+
+ private boolean evictCacheFlag = false;
+
+ public boolean isEvictCacheFlag() {
+ return evictCacheFlag;
+ }
+
+ public void setEvictCacheFlag(boolean evictCacheFlag) {
+ this.evictCacheFlag = evictCacheFlag;
+ }
@PostConstruct
public void init() throws IOException {
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/server/src/main/resources/ehcache-test.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/ehcache-test.xml b/server/src/main/resources/ehcache-test.xml
index bffe27a..5bd4d13 100644
--- a/server/src/main/resources/ehcache-test.xml
+++ b/server/src/main/resources/ehcache-test.xml
@@ -27,11 +27,4 @@
>
<persistence strategy="none"/>
</cache>
- <cache name="UserCache"
- eternal="false"
- timeToLiveSeconds="10800"
- memoryStoreEvictionPolicy="LRU"
- >
- <persistence strategy="none"/>
- </cache>
-</ehcache>
\ No newline at end of file
+</ehcache>
http://git-wip-us.apache.org/repos/asf/kylin/blob/3280172b/server/src/main/resources/ehcache.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/ehcache.xml b/server/src/main/resources/ehcache.xml
index 1d49ca6..c9efc13 100644
--- a/server/src/main/resources/ehcache.xml
+++ b/server/src/main/resources/ehcache.xml
@@ -27,11 +27,4 @@
>
<persistence strategy="none"/>
</cache>
- <cache name="UserCache"
- eternal="false"
- timeToLiveSeconds="10800"
- memoryStoreEvictionPolicy="LRU"
- >
- <persistence strategy="none"/>
- </cache>
-</ehcache>
\ No newline at end of file
+</ehcache>