mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-05 04:38:10 +08:00
PL-10002 REST request locale should be searched in the user language
This commit is contained in:
parent
def13fc838
commit
4f4009a5f6
@ -841,6 +841,7 @@ create table SYS_REST_API_TOKEN (
|
||||
AUTHENTICATION_BYTES longvarbinary,
|
||||
EXPIRY timestamp,
|
||||
USER_LOGIN varchar(50),
|
||||
LOCALE varchar(200),
|
||||
--
|
||||
primary key (ID)
|
||||
)^
|
||||
|
@ -900,6 +900,7 @@ create table SYS_REST_API_TOKEN (
|
||||
AUTHENTICATION_BYTES image,
|
||||
EXPIRY datetime,
|
||||
USER_LOGIN varchar(50),
|
||||
LOCALE varchar(200),
|
||||
--
|
||||
primary key (ID)
|
||||
)^
|
||||
|
@ -914,6 +914,7 @@ create table SYS_REST_API_TOKEN (
|
||||
AUTHENTICATION_BYTES longblob,
|
||||
EXPIRY datetime(3),
|
||||
USER_LOGIN varchar(50),
|
||||
LOCALE varchar(200),
|
||||
--
|
||||
primary key (ID)
|
||||
)^
|
||||
|
@ -691,6 +691,7 @@ create table SYS_REST_API_TOKEN (
|
||||
AUTHENTICATION_BYTES blob,
|
||||
EXPIRY timestamp,
|
||||
USER_LOGIN varchar2(50),
|
||||
LOCALE varchar2(200),
|
||||
--
|
||||
primary key (ID)
|
||||
)^
|
||||
|
@ -875,6 +875,7 @@ create table SYS_REST_API_TOKEN (
|
||||
AUTHENTICATION_BYTES bytea,
|
||||
EXPIRY timestamp,
|
||||
USER_LOGIN varchar(50),
|
||||
LOCALE varchar(200),
|
||||
--
|
||||
primary key (ID)
|
||||
)^
|
||||
|
@ -0,0 +1 @@
|
||||
alter table SYS_REST_API_TOKEN add LOCALE varchar(200)^
|
@ -0,0 +1 @@
|
||||
alter table SYS_REST_API_TOKEN add LOCALE varchar(200)^
|
@ -0,0 +1 @@
|
||||
alter table SYS_REST_API_TOKEN add LOCALE varchar(200)^
|
@ -0,0 +1 @@
|
||||
alter table SYS_REST_API_TOKEN add LOCALE varchar2(200);
|
@ -0,0 +1 @@
|
||||
alter table SYS_REST_API_TOKEN add LOCALE varchar(200)^
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.haulmont.cuba.restapi;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.haulmont.cuba.core.EntityManager;
|
||||
import com.haulmont.cuba.core.Persistence;
|
||||
import com.haulmont.cuba.core.Transaction;
|
||||
@ -33,6 +34,7 @@ import com.haulmont.cuba.security.auth.AuthenticationManager;
|
||||
import com.haulmont.cuba.security.global.NoUserSessionException;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.security.sys.UserSessionManager;
|
||||
import org.apache.commons.lang.LocaleUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -81,7 +83,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
private ConcurrentHashMap<String, byte[]> tokenValueToAccessTokenStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, byte[]> tokenValueToAuthenticationStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, byte[]> authenticationToAccessTokenStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, UUID> tokenValueToSessionIdStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, RestUserSessionInfo> tokenValueToSessionInfoStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, String> tokenValueToAuthenticationKeyStore = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, String> tokenValueToUserLoginStore = new ConcurrentHashMap<>();
|
||||
|
||||
@ -107,7 +109,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
@Override
|
||||
public byte[] getState() {
|
||||
if (tokenValueToAccessTokenStore.isEmpty() && tokenValueToAuthenticationStore.isEmpty() && authenticationToAccessTokenStore.isEmpty()
|
||||
&& tokenValueToSessionIdStore.isEmpty() && tokenValueToAuthenticationKeyStore.isEmpty()
|
||||
&& tokenValueToSessionInfoStore.isEmpty() && tokenValueToAuthenticationKeyStore.isEmpty()
|
||||
&& tokenValueToUserLoginStore.isEmpty()) {
|
||||
return new byte[0];
|
||||
}
|
||||
@ -120,7 +122,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
oos.writeObject(tokenValueToAccessTokenStore);
|
||||
oos.writeObject(tokenValueToAuthenticationStore);
|
||||
oos.writeObject(authenticationToAccessTokenStore);
|
||||
oos.writeObject(tokenValueToSessionIdStore);
|
||||
oos.writeObject(tokenValueToSessionInfoStore);
|
||||
oos.writeObject(tokenValueToAuthenticationKeyStore);
|
||||
oos.writeObject(tokenValueToUserLoginStore);
|
||||
} catch (IOException e) {
|
||||
@ -146,7 +148,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
tokenValueToAccessTokenStore = (ConcurrentHashMap<String, byte[]>) ois.readObject();
|
||||
tokenValueToAuthenticationStore = (ConcurrentHashMap<String, byte[]>) ois.readObject();
|
||||
authenticationToAccessTokenStore = (ConcurrentHashMap<String, byte[]>) ois.readObject();
|
||||
tokenValueToSessionIdStore = (ConcurrentHashMap<String, UUID>) ois.readObject();
|
||||
tokenValueToSessionInfoStore = (ConcurrentHashMap<String, RestUserSessionInfo>) ois.readObject();
|
||||
tokenValueToAuthenticationKeyStore = (ConcurrentHashMap<String, String>) ois.readObject();
|
||||
tokenValueToUserLoginStore = (ConcurrentHashMap<String, String>) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
@ -157,10 +159,10 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
}
|
||||
});
|
||||
|
||||
clusterManagerAPI.addListener(TokenStorePutSessionMsg.class, new ClusterListenerAdapter<TokenStorePutSessionMsg>() {
|
||||
clusterManagerAPI.addListener(TokenStorePutSessionInfoMsg.class, new ClusterListenerAdapter<TokenStorePutSessionInfoMsg>() {
|
||||
@Override
|
||||
public void receive(TokenStorePutSessionMsg message) {
|
||||
_putSessionId(message.getTokenValue(), message.getSessionId());
|
||||
public void receive(TokenStorePutSessionInfoMsg message) {
|
||||
_putSessionInfo(message.getTokenValue(), message.getSessionInfo());
|
||||
}
|
||||
});
|
||||
|
||||
@ -223,12 +225,14 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
String authenticationKey,
|
||||
byte[] authenticationBytes,
|
||||
Date tokenExpiry,
|
||||
String userLogin) {
|
||||
String userLogin,
|
||||
Locale locale) {
|
||||
storeAccessTokenToMemory(tokenValue, accessTokenBytes, authenticationKey, authenticationBytes, tokenExpiry, userLogin);
|
||||
if (serverConfig.getRestStoreTokensInDb()) {
|
||||
try (Transaction tx = persistence.getTransaction()) {
|
||||
removeAccessTokenFromDatabase(tokenValue);
|
||||
storeAccessTokenToDatabase(tokenValue, accessTokenBytes, authenticationKey, authenticationBytes, tokenExpiry, userLogin);
|
||||
storeAccessTokenToDatabase(tokenValue, accessTokenBytes, authenticationKey, authenticationBytes,
|
||||
tokenExpiry, userLogin, locale);
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
@ -263,7 +267,8 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
String authenticationKey,
|
||||
byte[] authenticationBytes,
|
||||
Date tokenExpiry,
|
||||
String userLogin) {
|
||||
String userLogin,
|
||||
@Nullable Locale locale) {
|
||||
try (Transaction tx = persistence.getTransaction()) {
|
||||
EntityManager em = persistence.getEntityManager();
|
||||
RestApiToken restApiToken = metadata.create(RestApiToken.class);
|
||||
@ -273,6 +278,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
restApiToken.setAuthenticationBytes(authenticationBytes);
|
||||
restApiToken.setExpiry(tokenExpiry);
|
||||
restApiToken.setUserLogin(userLogin);
|
||||
restApiToken.setLocale(locale != null ? locale.toString() : null);
|
||||
em.persist(restApiToken);
|
||||
tx.commit();
|
||||
}
|
||||
@ -358,21 +364,33 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getSessionIdByTokenValue(String tokenValue) {
|
||||
return tokenValueToSessionIdStore.get(tokenValue);
|
||||
public RestUserSessionInfo getSessionInfoByTokenValue(String tokenValue) {
|
||||
RestUserSessionInfo sessionInfo = tokenValueToSessionInfoStore.get(tokenValue);
|
||||
if (sessionInfo == null && serverConfig.getRestStoreTokensInDb()) {
|
||||
RestApiToken restApiToken = getRestApiTokenByTokenValueFromDatabase(tokenValue);
|
||||
if (restApiToken != null) {
|
||||
String localeStr = restApiToken.getLocale();
|
||||
if (!Strings.isNullOrEmpty(localeStr)) {
|
||||
Locale locale = LocaleUtils.toLocale(localeStr);
|
||||
return new RestUserSessionInfo(null, locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sessionInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID putSessionId(String tokenValue, UUID sessionId) {
|
||||
UUID uuid = _putSessionId(tokenValue, sessionId);
|
||||
clusterManagerAPI.send(new TokenStorePutSessionMsg(tokenValue, sessionId));
|
||||
return uuid;
|
||||
public RestUserSessionInfo putSessionInfo(String tokenValue, RestUserSessionInfo sessionInfo) {
|
||||
RestUserSessionInfo info = _putSessionInfo(tokenValue, sessionInfo);
|
||||
clusterManagerAPI.send(new TokenStorePutSessionInfoMsg(tokenValue, sessionInfo));
|
||||
return info;
|
||||
}
|
||||
|
||||
protected UUID _putSessionId(String tokenValue, UUID sessionId) {
|
||||
protected RestUserSessionInfo _putSessionInfo(String tokenValue, RestUserSessionInfo sessionInfo) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
return tokenValueToSessionIdStore.put(tokenValue, sessionId);
|
||||
return tokenValueToSessionInfoStore.put(tokenValue, sessionInfo);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
@ -388,7 +406,7 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
}
|
||||
|
||||
protected void removeAccessTokenFromMemory(String tokenValue) {
|
||||
UUID sessionId;
|
||||
RestUserSessionInfo sessionInfo;
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
tokenValueToAccessTokenStore.remove(tokenValue);
|
||||
@ -398,13 +416,13 @@ public class ServerTokenStoreImpl implements ServerTokenStore {
|
||||
if (authenticationKey != null) {
|
||||
authenticationToAccessTokenStore.remove(authenticationKey);
|
||||
}
|
||||
sessionId = tokenValueToSessionIdStore.remove(tokenValue);
|
||||
sessionInfo = tokenValueToSessionInfoStore.remove(tokenValue);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
if (sessionId != null) {
|
||||
if (sessionInfo != null) {
|
||||
try {
|
||||
UserSession session = userSessionManager.findSession(sessionId);
|
||||
UserSession session = userSessionManager.findSession(sessionInfo.getId());
|
||||
if (session != null) {
|
||||
AppContext.setSecurityContext(new SecurityContext(session));
|
||||
try {
|
||||
|
@ -22,20 +22,20 @@ import java.util.UUID;
|
||||
/**
|
||||
* Cluster message containing an information about the mapping between token value and middleware session
|
||||
*/
|
||||
public class TokenStorePutSessionMsg implements Serializable {
|
||||
public class TokenStorePutSessionInfoMsg implements Serializable {
|
||||
protected String tokenValue;
|
||||
protected UUID sessionId;
|
||||
protected RestUserSessionInfo sessionInfo;
|
||||
|
||||
public TokenStorePutSessionMsg(String tokenValue, UUID sessionId) {
|
||||
public TokenStorePutSessionInfoMsg(String tokenValue, RestUserSessionInfo sessionInfo) {
|
||||
this.tokenValue = tokenValue;
|
||||
this.sessionId = sessionId;
|
||||
this.sessionInfo = sessionInfo;
|
||||
}
|
||||
|
||||
public String getTokenValue() {
|
||||
return tokenValue;
|
||||
}
|
||||
|
||||
public UUID getSessionId() {
|
||||
return sessionId;
|
||||
public RestUserSessionInfo getSessionInfo() {
|
||||
return sessionInfo;
|
||||
}
|
||||
}
|
@ -54,6 +54,9 @@ public class RestApiToken extends BaseUuidEntity implements Creatable{
|
||||
@Column(name = "USER_LOGIN")
|
||||
protected String userLogin;
|
||||
|
||||
@Column(name = "LOCALE")
|
||||
protected String locale;
|
||||
|
||||
public String getAccessTokenValue() {
|
||||
return accessTokenValue;
|
||||
}
|
||||
@ -121,4 +124,12 @@ public class RestApiToken extends BaseUuidEntity implements Creatable{
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2017 Haulmont.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.restapi;
|
||||
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class RestUserSessionInfo implements Serializable {
|
||||
|
||||
protected UUID id;
|
||||
|
||||
protected Locale locale;
|
||||
|
||||
public RestUserSessionInfo(UserSession userSession) {
|
||||
this.id = userSession.getId();
|
||||
this.locale = userSession.getLocale();
|
||||
}
|
||||
|
||||
public RestUserSessionInfo(UUID id, Locale locale) {
|
||||
this.id = id;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
}
|
@ -17,8 +17,8 @@
|
||||
package com.haulmont.cuba.restapi;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* OAuth token store for the REST API.
|
||||
@ -31,15 +31,16 @@ public interface ServerTokenStore {
|
||||
|
||||
Set<String> getTokenValuesByUserLogin(String userLogin);
|
||||
|
||||
void storeAccessToken(String tokenValue, byte[] accessTokenBytes, String authenticationKey, byte[] authenticationBytes, Date tokenExpiry, String userLogin);
|
||||
void storeAccessToken(String tokenValue, byte[] accessTokenBytes, String authenticationKey,
|
||||
byte[] authenticationBytes, Date tokenExpiry, String userLogin, Locale locale);
|
||||
|
||||
byte[] getAccessTokenByTokenValue(String tokenValue);
|
||||
|
||||
byte[] getAuthenticationByTokenValue(String tokenValue);
|
||||
|
||||
UUID getSessionIdByTokenValue(String authenticationKey);
|
||||
RestUserSessionInfo getSessionInfoByTokenValue(String tokenValue);
|
||||
|
||||
UUID putSessionId(String authenticationKey, UUID sessionId);
|
||||
RestUserSessionInfo putSessionInfo(String tokenValue, RestUserSessionInfo sessionInfo);
|
||||
|
||||
void removeAccessToken(String tokenValue);
|
||||
|
||||
|
@ -21,12 +21,14 @@ import com.haulmont.cuba.core.global.ClientType;
|
||||
import com.haulmont.cuba.core.global.GlobalConfig;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.core.sys.SecurityContext;
|
||||
import com.haulmont.cuba.restapi.RestUserSessionInfo;
|
||||
import com.haulmont.cuba.restapi.ServerTokenStore;
|
||||
import com.haulmont.cuba.security.app.TrustedClientService;
|
||||
import com.haulmont.cuba.security.auth.AuthenticationService;
|
||||
import com.haulmont.cuba.security.auth.TrustedClientCredentials;
|
||||
import com.haulmont.cuba.security.global.LoginException;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.restapi.common.RestAuthUtils;
|
||||
import com.haulmont.restapi.config.RestApiConfig;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpHeaders;
|
||||
@ -73,6 +75,9 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
|
||||
protected AuthenticationKeyGenerator authenticationKeyGenerator;
|
||||
|
||||
@Inject
|
||||
protected RestAuthUtils restAuthUtils;
|
||||
|
||||
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
|
||||
this.authenticationKeyGenerator = authenticationKeyGenerator;
|
||||
}
|
||||
@ -96,12 +101,18 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
String authenticationKey = authenticationKeyGenerator.extractKey(authentication);
|
||||
String userLogin = authentication.getName();
|
||||
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
Locale locale = restAuthUtils.extractLocaleFromRequestHeader(request);
|
||||
|
||||
serverTokenStore.storeAccessToken(token.getValue(),
|
||||
serializeAccessToken(token),
|
||||
authenticationKey,
|
||||
serializeAuthentication(authentication),
|
||||
token.getExpiration(),
|
||||
userLogin);
|
||||
userLogin,
|
||||
locale);
|
||||
processSession(authentication, token.getValue());
|
||||
log.info("REST API access token stored: [{}] {}", authentication.getPrincipal(), token.getValue()) ;
|
||||
}
|
||||
@ -130,8 +141,8 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
* the id doesn't exist in the middleware, then the trusted login attempt is performed.
|
||||
*/
|
||||
protected void processSession(OAuth2Authentication authentication, String tokenValue) {
|
||||
UUID sessionId = serverTokenStore.getSessionIdByTokenValue(tokenValue);
|
||||
|
||||
RestUserSessionInfo sessionInfo = serverTokenStore.getSessionInfoByTokenValue(tokenValue);
|
||||
UUID sessionId = sessionInfo != null ? sessionInfo.getId() : null;
|
||||
if (sessionId == null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> userAuthenticationDetails =
|
||||
@ -160,9 +171,11 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
try {
|
||||
ServletRequestAttributes attributes =
|
||||
(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
|
||||
Locale locale = sessionInfo != null ?
|
||||
sessionInfo.getLocale() :
|
||||
null;
|
||||
TrustedClientCredentials credentials = new TrustedClientCredentials(username,
|
||||
restApiConfig.getTrustedClientPassword(), getDefaultLocale());
|
||||
restApiConfig.getTrustedClientPassword(), locale);
|
||||
credentials.setClientType(ClientType.REST_API);
|
||||
if (attributes != null) {
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
@ -172,6 +185,11 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
credentials.setClientInfo(makeClientInfo(""));
|
||||
}
|
||||
|
||||
//if locale was not determined then use the user locale
|
||||
if (locale == null) {
|
||||
credentials.setOverrideLocale(false);
|
||||
}
|
||||
|
||||
session = authenticationService.login(credentials).getSession();
|
||||
} catch (LoginException e) {
|
||||
throw new OAuth2Exception("Cannot login to the middleware");
|
||||
@ -179,7 +197,7 @@ public class ClientProxyTokenStore implements TokenStore {
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
serverTokenStore.putSessionId(tokenValue, session.getId());
|
||||
serverTokenStore.putSessionInfo(tokenValue, new RestUserSessionInfo(session));
|
||||
AppContext.setSecurityContext(new SecurityContext(session));
|
||||
}
|
||||
}
|
||||
|
@ -17,18 +17,15 @@
|
||||
package com.haulmont.restapi.auth;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.haulmont.cuba.core.global.Configuration;
|
||||
import com.haulmont.cuba.core.global.Events;
|
||||
import com.haulmont.cuba.core.global.GlobalConfig;
|
||||
import com.haulmont.cuba.core.global.MessageTools;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.core.sys.SecurityContext;
|
||||
import com.haulmont.cuba.core.sys.UserInvocationContext;
|
||||
import com.haulmont.restapi.common.RestAuthUtils;
|
||||
import com.haulmont.restapi.events.AfterRestInvocationEvent;
|
||||
import com.haulmont.restapi.events.BeforeRestInvocationEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
|
||||
@ -39,7 +36,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -56,11 +52,16 @@ public class CubaRestLastSecurityFilter implements Filter {
|
||||
|
||||
@Inject
|
||||
protected Configuration configuration;
|
||||
|
||||
@Inject
|
||||
protected MessageTools messageTools;
|
||||
|
||||
@Inject
|
||||
protected Events events;
|
||||
|
||||
@Inject
|
||||
protected RestAuthUtils restAuthUtils;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// do nothing
|
||||
@ -126,26 +127,14 @@ public class CubaRestLastSecurityFilter implements Filter {
|
||||
* Method parses the request locale and sets it to the {@link UserInvocationContext}
|
||||
*/
|
||||
protected void parseRequestLocale(ServletRequest request) {
|
||||
//Take the locale value either from the 'Accept-Language' http header or take the default one
|
||||
Locale locale = null;
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
if (!Strings.isNullOrEmpty(httpServletRequest.getHeader(HttpHeaders.ACCEPT_LANGUAGE))) {
|
||||
Locale requestLocale = request.getLocale();
|
||||
|
||||
GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class);
|
||||
Map<String, Locale> availableLocales = globalConfig.getAvailableLocales();
|
||||
if (availableLocales.values().contains(requestLocale)) {
|
||||
locale = requestLocale;
|
||||
}
|
||||
}
|
||||
if (locale == null) {
|
||||
locale = messageTools.getDefaultLocale();
|
||||
}
|
||||
SecurityContext securityContext = AppContext.getSecurityContext();
|
||||
if (securityContext != null) {
|
||||
UUID sessionId = securityContext.getSessionId();
|
||||
if (sessionId != null) {
|
||||
UserInvocationContext.setRequestScopeInfo(sessionId, locale, null, null, null);
|
||||
Locale locale = restAuthUtils.extractLocaleFromRequestHeader((HttpServletRequest) request);
|
||||
if (locale != null) {
|
||||
SecurityContext securityContext = AppContext.getSecurityContext();
|
||||
if (securityContext != null) {
|
||||
UUID sessionId = securityContext.getSessionId();
|
||||
if (sessionId != null) {
|
||||
UserInvocationContext.setRequestScopeInfo(sessionId, locale, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import com.haulmont.cuba.security.global.RestApiAccessDeniedException;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import com.haulmont.restapi.common.RestAuthUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
@ -49,6 +50,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class CubaUserAuthenticationProvider implements AuthenticationProvider, Serializable {
|
||||
@ -66,6 +68,9 @@ public class CubaUserAuthenticationProvider implements AuthenticationProvider, S
|
||||
@Inject
|
||||
protected Configuration configuration;
|
||||
|
||||
@Inject
|
||||
protected RestAuthUtils restAuthUtils;
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
@ -89,11 +94,21 @@ public class CubaUserAuthenticationProvider implements AuthenticationProvider, S
|
||||
try {
|
||||
String passwordHash = passwordEncryption.getPlainHash((String) token.getCredentials());
|
||||
|
||||
LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, passwordHash, request.getLocale());
|
||||
LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, passwordHash);
|
||||
credentials.setIpAddress(ipAddress);
|
||||
credentials.setClientType(ClientType.REST_API);
|
||||
credentials.setClientInfo(makeClientInfo(request.getHeader(HttpHeaders.USER_AGENT)));
|
||||
|
||||
//if the locale value is explicitly passed in the Accept-Language header then set its value to the
|
||||
//credentials. Otherwise, the locale of the user should be used
|
||||
Locale locale = restAuthUtils.extractLocaleFromRequestHeader(request);
|
||||
if (locale != null) {
|
||||
credentials.setLocale(locale);
|
||||
credentials.setOverrideLocale(true);
|
||||
} else {
|
||||
credentials.setOverrideLocale(false);
|
||||
}
|
||||
|
||||
session = authenticationService.login(credentials).getSession();
|
||||
} catch (AccountLockedException le) {
|
||||
log.info("Blocked user login attempt: login={}, ip={}", login, ipAddress);
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2017 Haulmont.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.haulmont.restapi.common;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.haulmont.cuba.core.global.Configuration;
|
||||
import com.haulmont.cuba.core.global.GlobalConfig;
|
||||
import com.haulmont.cuba.core.global.MessageTools;
|
||||
import com.haulmont.cuba.core.global.UserSessionSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* REST API authentication utility class
|
||||
*/
|
||||
@Component("cuba_RestAuthUtils")
|
||||
public class RestAuthUtils {
|
||||
|
||||
@Inject
|
||||
protected Configuration configuration;
|
||||
|
||||
@Inject
|
||||
protected UserSessionSource userSessionSource;
|
||||
|
||||
@Inject
|
||||
protected MessageTools messageTools;
|
||||
|
||||
protected Logger log = LoggerFactory.getLogger(RestAuthUtils.class);
|
||||
|
||||
/**
|
||||
* Method extracts locale information from the Accept-Language header. If no such header is specified or the
|
||||
* passed locale is not among application available locales, then null is returned
|
||||
*/
|
||||
@Nullable
|
||||
public Locale extractLocaleFromRequestHeader(HttpServletRequest request) {
|
||||
Locale locale = null;
|
||||
if (!Strings.isNullOrEmpty(request.getHeader(HttpHeaders.ACCEPT_LANGUAGE))) {
|
||||
Locale requestLocale = request.getLocale();
|
||||
|
||||
GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class);
|
||||
Map<String, Locale> availableLocales = globalConfig.getAvailableLocales();
|
||||
if (availableLocales.values().contains(requestLocale)) {
|
||||
locale = requestLocale;
|
||||
} else {
|
||||
log.warn("Locale {} passed in the Accept-Language header is not supported by the application. It was ignored.");
|
||||
}
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user