mirror of
https://gitee.com/dromara/MaxKey.git
synced 2026-05-15 04:52:09 +08:00
init spring
This commit is contained in:
@@ -42,10 +42,10 @@ public abstract class AbstractAuthenticationProvider{
|
||||
@Qualifier("tfaOTPAuthn")
|
||||
protected AbstractOTPAuthn tfaOTPAuthn;
|
||||
|
||||
@Autowired
|
||||
/* @Autowired
|
||||
@Qualifier("jwtLoginService")
|
||||
JwtLoginService jwtLoginService;
|
||||
|
||||
*/
|
||||
protected abstract String getProviderName();
|
||||
|
||||
protected abstract Authentication doInternalAuthenticate(Authentication authentication);
|
||||
@@ -61,14 +61,13 @@ public abstract class AbstractAuthenticationProvider{
|
||||
* @see org.springframework.security.authentication.AuthenticationProvider#authenticate(org.springframework.security.core.Authentication)
|
||||
*/
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
String username = authentication.getName();
|
||||
_logger.debug("Trying to authenticate user '{}' via {}", username, getProviderName());
|
||||
_logger.debug("Trying to authenticate user '{}' via {}", authentication.getPrincipal(), getProviderName());
|
||||
|
||||
try {
|
||||
authentication = doInternalAuthenticate(authentication);
|
||||
} catch (AuthenticationException e) {
|
||||
e.printStackTrace();
|
||||
_logger.error("Failed to authenticate user {} via {}: {}", new Object[]{username, getProviderName(), e.getMessage()});
|
||||
_logger.error("Failed to authenticate user {} via {}: {}", new Object[]{authentication.getPrincipal(), getProviderName(), e.getMessage()});
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -81,7 +80,7 @@ public abstract class AbstractAuthenticationProvider{
|
||||
}
|
||||
|
||||
// user authenticated
|
||||
_logger.debug("'{}' authenticated successfully by {}.", username, getProviderName());
|
||||
_logger.debug("'{0}' authenticated successfully by {}.", authentication.getPrincipal(), getProviderName());
|
||||
|
||||
UserInfo userInfo=WebContext.getUserInfo();
|
||||
WebContext.setAttribute(WebConstants.CURRENT_USER_SESSION_ID, WebContext.getSession().getId());
|
||||
@@ -115,11 +114,11 @@ public abstract class AbstractAuthenticationProvider{
|
||||
* @param sessionId
|
||||
*/
|
||||
protected void jwtTokenValid(String j_jwtToken){
|
||||
if(j_jwtToken!=null && ! j_jwtToken.equals("")){
|
||||
/*if(j_jwtToken!=null && ! j_jwtToken.equals("")){
|
||||
if(jwtLoginService.jwtTokenValidation(j_jwtToken)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
String message=WebContext.getI18nValue("login.error.session");
|
||||
_logger.debug("login session valid error.");
|
||||
throw new BadCredentialsException(message);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package org.maxkey.authn;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class BasicAuthentication implements Authentication{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -110742975439268030L;
|
||||
String j_username ;
|
||||
String j_password ;
|
||||
String j_sessionid;
|
||||
String j_captcha;
|
||||
String j_otp_captcha;
|
||||
String j_remeberme;
|
||||
String j_auth_type;
|
||||
String j_jwt_token;
|
||||
|
||||
boolean authenticated;
|
||||
|
||||
public BasicAuthentication() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Basic Authentication";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return this.getJ_password();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDetails() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.getJ_username();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
|
||||
this.authenticated=authenticated;
|
||||
|
||||
}
|
||||
|
||||
public String getJ_username() {
|
||||
return j_username;
|
||||
}
|
||||
|
||||
public void setJ_username(String j_username) {
|
||||
this.j_username = j_username;
|
||||
}
|
||||
|
||||
public String getJ_password() {
|
||||
return j_password;
|
||||
}
|
||||
|
||||
public void setJ_password(String j_password) {
|
||||
this.j_password = j_password;
|
||||
}
|
||||
|
||||
public String getJ_sessionid() {
|
||||
return j_sessionid;
|
||||
}
|
||||
|
||||
public void setJ_sessionid(String j_sessionid) {
|
||||
this.j_sessionid = j_sessionid;
|
||||
}
|
||||
|
||||
public String getJ_captcha() {
|
||||
return j_captcha;
|
||||
}
|
||||
|
||||
public void setJ_captcha(String j_captcha) {
|
||||
this.j_captcha = j_captcha;
|
||||
}
|
||||
|
||||
public String getJ_otp_captcha() {
|
||||
return j_otp_captcha;
|
||||
}
|
||||
|
||||
public void setJ_otp_captcha(String j_otp_captcha) {
|
||||
this.j_otp_captcha = j_otp_captcha;
|
||||
}
|
||||
|
||||
public String getJ_remeberme() {
|
||||
return j_remeberme;
|
||||
}
|
||||
|
||||
public void setJ_remeberme(String j_remeberme) {
|
||||
this.j_remeberme = j_remeberme;
|
||||
}
|
||||
|
||||
public String getJ_auth_type() {
|
||||
return j_auth_type;
|
||||
}
|
||||
|
||||
public void setJ_auth_type(String j_auth_type) {
|
||||
this.j_auth_type = j_auth_type;
|
||||
}
|
||||
|
||||
public String getJ_jwt_token() {
|
||||
return j_jwt_token;
|
||||
}
|
||||
|
||||
public void setJ_jwt_token(String j_jwt_token) {
|
||||
this.j_jwt_token = j_jwt_token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BasicAuthentication [j_username=" + j_username + ", j_sessionId=" + j_sessionid + ", j_captcha="
|
||||
+ j_captcha + ", j_otp_captcha=" + j_otp_captcha + ", j_remeberMe=" + j_remeberme + ", j_auth_type="
|
||||
+ j_auth_type + ", j_jwtToken=" + j_jwt_token + ", authenticated=" + authenticated + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.maxkey.authn;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.maxkey.domain.UserInfo;
|
||||
import org.maxkey.web.WebConstants;
|
||||
import org.maxkey.web.WebContext;
|
||||
@@ -22,68 +20,52 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
|
||||
private static final Logger _logger = LoggerFactory.getLogger(RealmAuthenticationProvider.class);
|
||||
|
||||
protected String getProviderName() {
|
||||
return "UserInfo";
|
||||
return "RealmAuthenticationProvider";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication doInternalAuthenticate(Authentication authentication) {
|
||||
HttpSession session = WebContext.getSession();
|
||||
// All your user authentication needs
|
||||
String j_username = (String) authentication.getPrincipal();
|
||||
String j_password = (String) authentication.getCredentials();
|
||||
String j_sessionId=WebContext.getRequest().getParameter("j_sessionid");
|
||||
String j_captcha=WebContext.getRequest().getParameter("j_captcha");
|
||||
String j_otp_captcha=WebContext.getRequest().getParameter("j_otp_captcha");
|
||||
String j_remeberMe=WebContext.getRequest().getParameter("j_remeberMe");
|
||||
String j_auth_type=WebContext.getRequest().getParameter("j_auth_type");
|
||||
String j_jwtToken=WebContext.getRequest().getParameter("j_jwttoken");
|
||||
BasicAuthentication auth =(BasicAuthentication)authentication;
|
||||
|
||||
_logger.info("principal : "+j_username);
|
||||
_logger.info("credentials : PROTECTED");
|
||||
_logger.info("j_auth_type input : "+j_auth_type);
|
||||
_logger.info("captcha input : "+j_captcha);
|
||||
_logger.info("j_otp_captcha input : "+j_otp_captcha);
|
||||
_logger.info("sessionId : "+j_sessionId);
|
||||
_logger.info("session getId() : "+session.getId());
|
||||
_logger.info("Authentication principal :"+authentication.getName()+" , credentials : ********");
|
||||
_logger.debug("authentication "+auth);
|
||||
|
||||
sessionValid(j_sessionId);
|
||||
sessionValid(auth.getJ_sessionid());
|
||||
|
||||
jwtTokenValid(j_jwtToken);
|
||||
//jwtTokenValid(j_jwtToken);
|
||||
|
||||
authTypeValid(j_auth_type);
|
||||
authTypeValid(auth.getJ_auth_type());
|
||||
|
||||
captchaValid(j_captcha,j_auth_type);
|
||||
captchaValid(auth.getJ_captcha(),auth.getJ_auth_type());
|
||||
|
||||
emptyPasswordValid(j_password);
|
||||
emptyPasswordValid(auth.getJ_password());
|
||||
|
||||
UserInfo userInfo = null;
|
||||
|
||||
emptyUsernameValid(j_username);
|
||||
emptyUsernameValid(auth.getJ_username());
|
||||
|
||||
userInfo= loadUserInfo(j_username,j_password);
|
||||
userInfo= loadUserInfo(auth.getJ_username(),auth.getJ_password());
|
||||
|
||||
userinfoValid(userInfo, j_username);
|
||||
userinfoValid(userInfo, auth.getJ_password());
|
||||
|
||||
tftcaptchaValid(j_otp_captcha,j_auth_type,userInfo);
|
||||
tftcaptchaValid(auth.getJ_otp_captcha(),auth.getJ_auth_type(),userInfo);
|
||||
|
||||
authenticationRealm.passwordPolicyValid(userInfo);
|
||||
|
||||
authenticationRealm.passwordMatches(userInfo, j_password);
|
||||
authenticationRealm.passwordMatches(userInfo, auth.getJ_password());
|
||||
/**
|
||||
* put userInfo to current session context
|
||||
*/
|
||||
WebContext.setUserInfo(userInfo);
|
||||
|
||||
if(applicationConfig.getLoginConfig().isRemeberMe()){
|
||||
if(j_remeberMe!=null&&j_remeberMe.equals("remeberMe")){
|
||||
WebContext.getSession().setAttribute(WebConstants.REMEBER_ME_SESSION,j_username);
|
||||
if(auth.getJ_remeberme()!=null&&auth.getJ_remeberme().equals("remeberMe")){
|
||||
WebContext.getSession().setAttribute(WebConstants.REMEBER_ME_SESSION,auth.getJ_username());
|
||||
_logger.debug("do Remeber Me");
|
||||
}
|
||||
}
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =new UsernamePasswordAuthenticationToken(
|
||||
userInfo,
|
||||
j_password,
|
||||
auth.getJ_password(),
|
||||
authenticationRealm.grantAuthorityAndNavs(userInfo));
|
||||
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(WebContext.getRequest()));
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ public abstract class AbstractAuthenticationRealm{
|
||||
return true;
|
||||
}
|
||||
|
||||
public UserInfo loadUserInfo(String username,String j_password) {
|
||||
public UserInfo loadUserInfo(String username,String password) {
|
||||
List<UserInfo> listUserInfo=jdbcTemplate.query(
|
||||
DEFAULT_USERINFO_SELECT_STATEMENT,
|
||||
new UserInfoRowMapper(),
|
||||
@@ -156,7 +156,7 @@ public abstract class AbstractAuthenticationRealm{
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
public abstract boolean passwordMatches(UserInfo userInfo,String j_password);
|
||||
public abstract boolean passwordMatches(UserInfo userInfo,String password);
|
||||
|
||||
|
||||
public static boolean isAuthenticated(){
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.maxkey.config;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.mybatis.jpa.dialect.Dialect;
|
||||
import org.maxkey.crypto.Base64Utils;
|
||||
import org.maxkey.crypto.ReciprocalUtils;
|
||||
import org.maxkey.crypto.password.PasswordReciprocal;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
@@ -82,13 +82,14 @@ public class DataSoruceConfig {
|
||||
String decodePassword="";
|
||||
LogFactory.getLog(DataSoruceConfig.class).debug("password is "+password);
|
||||
if(encrypt){
|
||||
decodePassword = ReciprocalUtils.decoder(password);
|
||||
decodePassword = PasswordReciprocal.getInstance().decoder(password);
|
||||
}else{
|
||||
decodePassword= password;
|
||||
}
|
||||
LogFactory.getLog(DataSoruceConfig.class).debug("password is "+password+" , decodePassword is "+Base64Utils.encode(decodePassword));
|
||||
LogFactory.getLog(DataSoruceConfig.class).debug("password is "+password+" , decodePassword is "+decodePassword);
|
||||
return decodePassword;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import com.nimbusds.jose.jwk.JWKSet;
|
||||
public class RecipientJwtEncryptionAndDecryptionServiceBuilder {
|
||||
final static Logger logger = Logger.getLogger(RecipientJwtEncryptionAndDecryptionServiceBuilder.class);
|
||||
|
||||
private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
|
||||
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
private RestTemplate restTemplate = new RestTemplate(httpFactory);
|
||||
//private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
|
||||
//private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
//private RestTemplate restTemplate = new RestTemplate(httpFactory);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -39,7 +39,7 @@ public class RecipientJwtEncryptionAndDecryptionServiceBuilder {
|
||||
|
||||
logger.debug("jwksUri : "+jwksUri);
|
||||
|
||||
String jsonString = restTemplate.getForObject(jwksUri, String.class);
|
||||
String jsonString ="";//= restTemplate.getForObject(jwksUri, String.class);
|
||||
|
||||
logger.debug("jwks json String : "+jsonString);
|
||||
JwtEncryptionAndDecryptionService recipientJwtEncryptionAndDecryptionService;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.maxkey.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.mybatis.jpa.persistence.JpaBaseDomain;
|
||||
|
||||
public class Organizations extends JpaBaseDomain implements Serializable{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5085413816404119803L;
|
||||
|
||||
public Organizations() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -95,7 +95,8 @@ public class RedisConnectionFactory {
|
||||
}
|
||||
|
||||
public void close(Jedis conn){
|
||||
jedisPool.returnResource(conn);
|
||||
//jedisPool.returnResource(conn);
|
||||
conn.close();
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
|
||||
@@ -41,7 +41,8 @@ public class PathUtils {
|
||||
classPath=classPath.substring(5, classPath.length());
|
||||
}
|
||||
|
||||
classPath=classPath.substring(0,classPath.indexOf("/com/connsec/util/PathUtils.properties"));
|
||||
_logger.info("PathUtils Class Path : " + classPath);
|
||||
classPath=classPath.substring(0,classPath.indexOf("/org/maxkey/util/PathUtils.properties"));
|
||||
if(classPath.indexOf(WEB_INFO)==-1) {
|
||||
appPath=classPath.substring(0,classPath.lastIndexOf("/"));
|
||||
}else {
|
||||
|
||||
@@ -1,69 +1,422 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.maxkey.web.tag;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
import org.maxkey.web.WebContext;
|
||||
import javax.servlet.jsp.JspTagException;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceResolvable;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.tags.ArgumentAware;
|
||||
import org.springframework.web.servlet.tags.HtmlEscapingAwareTag;
|
||||
import org.springframework.web.util.JavaScriptUtils;
|
||||
import org.springframework.web.util.TagUtils;
|
||||
|
||||
/**
|
||||
* 本地语言标签
|
||||
* 国际化使用
|
||||
* @author Crystal.Sea
|
||||
* The {@code <message>} tag looks up a message in the scope of this page.
|
||||
* Messages are resolved using the ApplicationContext and thus support
|
||||
* internationalization.
|
||||
*
|
||||
* <p>Detects an HTML escaping setting, either on this tag instance, the page level,
|
||||
* or the {@code web.xml} level. Can also apply JavaScript escaping.
|
||||
*
|
||||
* <p>If "code" isn't set or cannot be resolved, "text" will be used as default
|
||||
* message. Thus, this tag can also be used for HTML escaping of any texts.
|
||||
*
|
||||
* <p>Message arguments can be specified via the {@link #setArguments(Object) arguments}
|
||||
* attribute or by using nested {@code <spring:argument>} tags.
|
||||
*
|
||||
* <table>
|
||||
* <caption>Attribute Summary</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th>Attribute</th>
|
||||
* <th>Required?</th>
|
||||
* <th>Runtime Expression?</th>
|
||||
* <th>Description</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <td>arguments</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>Set optional message arguments for this tag, as a (comma-)delimited
|
||||
* String (each String argument can contain JSP EL), an Object array (used as
|
||||
* argument array), or a single Object (used as single argument).</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>argumentSeparator</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>The separator character to be used for splitting the arguments string
|
||||
* value; defaults to a 'comma' (',').</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>code</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>The code (key) to use when looking up the message.
|
||||
* If code is not provided, the text attribute will be used.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>htmlEscape</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>Set HTML escaping for this tag, as boolean value.
|
||||
* Overrides the default HTML escaping setting for the current page.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>javaScriptEscape</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>Set JavaScript escaping for this tag, as boolean value.
|
||||
* Default is false.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>message</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>A MessageSourceResolvable argument (direct or through JSP EL).
|
||||
* Fits nicely when used in conjunction with Spring’s own validation error
|
||||
* classes which all implement the MessageSourceResolvable interface.
|
||||
* For example, this allows you to iterate over all of the errors in a form,
|
||||
* passing each error (using a runtime expression) as the value of this
|
||||
* 'message' attribute, thus effecting the easy display of such error
|
||||
* messages.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>scope</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>The scope to use when exporting the result to a variable. This attribute
|
||||
* is only used when var is also set. Possible values are page, request, session
|
||||
* and application.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>text</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>Default text to output when a message for the given code could not be
|
||||
* found. If both text and code are not set, the tag will output null.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>var</td>
|
||||
* <td>false</td>
|
||||
* <td>true</td>
|
||||
* <td>The string to use when binding the result to the page, request, session
|
||||
* or application scope. If not specified, the result gets outputted to the writer
|
||||
* (i.e. typically directly to the JSP).</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Nicholas Williams
|
||||
* @see #setCode
|
||||
* @see #setText
|
||||
* @see #setHtmlEscape
|
||||
* @see #setJavaScriptEscape
|
||||
* @see HtmlEscapeTag#setDefaultHtmlEscape
|
||||
* @see org.springframework.web.util.WebUtils#HTML_ESCAPE_CONTEXT_PARAM
|
||||
* @see ArgumentTag
|
||||
*/
|
||||
public class LocaleTag extends TagSupport{
|
||||
@SuppressWarnings("serial")
|
||||
public class LocaleTag extends HtmlEscapingAwareTag implements ArgumentAware {
|
||||
|
||||
/**
|
||||
*
|
||||
* Default separator for splitting an arguments String: a comma (",").
|
||||
*/
|
||||
private static final long serialVersionUID = -3906613920420893358L;
|
||||
|
||||
private PageContext pageContext;
|
||||
|
||||
public static final String DEFAULT_ARGUMENT_SEPARATOR = ",";
|
||||
|
||||
|
||||
@Nullable
|
||||
private MessageSourceResolvable message;
|
||||
|
||||
@Nullable
|
||||
private String code;
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
private Object arguments;
|
||||
|
||||
private String argumentSeparator = DEFAULT_ARGUMENT_SEPARATOR;
|
||||
|
||||
private List<Object> nestedArguments = Collections.emptyList();
|
||||
|
||||
@Nullable
|
||||
private String text;
|
||||
|
||||
@Nullable
|
||||
private String var;
|
||||
|
||||
private String scope = TagUtils.SCOPE_PAGE;
|
||||
|
||||
private boolean javaScriptEscape = false;
|
||||
|
||||
|
||||
/**
|
||||
* @param code the code to set
|
||||
* Set the MessageSourceResolvable for this tag.
|
||||
* <p>If a MessageSourceResolvable is specified, it effectively overrides
|
||||
* any code, arguments or text specified on this tag.
|
||||
*/
|
||||
public void setMessage(MessageSourceResolvable message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message code for this tag.
|
||||
*/
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public void setPageContext(PageContext pageContext) {
|
||||
this.pageContext = pageContext;
|
||||
/**
|
||||
* Set optional message arguments for this tag, as a comma-delimited
|
||||
* String (each String argument can contain JSP EL), an Object array
|
||||
* (used as argument array), or a single Object (used as single argument).
|
||||
*/
|
||||
public void setArguments(Object arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public final int doStartTag() throws JspException{
|
||||
return SKIP_BODY;
|
||||
|
||||
/**
|
||||
* Set the separator to use for splitting an arguments String.
|
||||
* Default is a comma (",").
|
||||
* @see #setArguments
|
||||
*/
|
||||
public void setArgumentSeparator(String argumentSeparator) {
|
||||
this.argumentSeparator = argumentSeparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addArgument(@Nullable Object argument) throws JspTagException {
|
||||
this.nestedArguments.add(argument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message text for this tag.
|
||||
*/
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PageContext attribute name under which to expose
|
||||
* a variable that contains the resolved message.
|
||||
* @see #setScope
|
||||
* @see javax.servlet.jsp.PageContext#setAttribute
|
||||
*/
|
||||
public void setVar(String var) {
|
||||
this.var = var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scope to export the variable to.
|
||||
* Default is SCOPE_PAGE ("page").
|
||||
* @see #setVar
|
||||
* @see org.springframework.web.util.TagUtils#SCOPE_PAGE
|
||||
* @see javax.servlet.jsp.PageContext#setAttribute
|
||||
*/
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set JavaScript escaping for this tag, as boolean value.
|
||||
* Default is "false".
|
||||
*/
|
||||
public void setJavaScriptEscape(boolean javaScriptEscape) throws JspException {
|
||||
this.javaScriptEscape = javaScriptEscape;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected final int doStartTagInternal() throws JspException, IOException {
|
||||
this.nestedArguments = new LinkedList<>();
|
||||
return EVAL_BODY_INCLUDE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the message, escapes it if demanded,
|
||||
* and writes it to the page (or exposes it as variable).
|
||||
* @see #resolveMessage()
|
||||
* @see org.springframework.web.util.HtmlUtils#htmlEscape(String)
|
||||
* @see org.springframework.web.util.JavaScriptUtils#javaScriptEscape(String)
|
||||
* @see #writeMessage(String)
|
||||
*/
|
||||
@Override
|
||||
public int doEndTag() throws JspException {
|
||||
try {
|
||||
if(code==null) {
|
||||
pageContext.getOut().print(getRequestContext().getLocale());
|
||||
}else {
|
||||
// Resolve the unescaped message.
|
||||
String msg = resolveMessage();
|
||||
|
||||
public final int doEndTag() throws JspException{
|
||||
int tagReturn=EVAL_PAGE;
|
||||
try{
|
||||
if(null==code){
|
||||
pageContext.getOut().print(WebContext.getRequestLocale());
|
||||
}else{
|
||||
String localeText=WebContext.getI18nValue(code);
|
||||
if(localeText==null||localeText.equals("")){
|
||||
String []localPath=code.split("\\.");
|
||||
localeText=localPath[(localPath.length>1?localPath.length-1:0)];
|
||||
localeText=localeText.toUpperCase().charAt(0)+localeText.substring(1);
|
||||
// HTML and/or JavaScript escape, if demanded.
|
||||
msg = htmlEscape(msg);
|
||||
msg = this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(msg) : msg;
|
||||
|
||||
// Expose as variable, if demanded, else write to the page.
|
||||
if (this.var != null) {
|
||||
this.pageContext.setAttribute(this.var, msg, TagUtils.getScope(this.scope));
|
||||
}
|
||||
else {
|
||||
writeMessage(msg);
|
||||
}
|
||||
pageContext.getOut().print(localeText);
|
||||
}
|
||||
|
||||
pageContext.getOut().flush();
|
||||
} catch (IOException e){
|
||||
throw new JspException("exception="+e.getMessage());
|
||||
return EVAL_PAGE;
|
||||
}
|
||||
return tagReturn;
|
||||
|
||||
catch (IOException ex) {
|
||||
System.out.println("IOException code "+code);
|
||||
throw new JspTagException(ex.getMessage(), ex);
|
||||
}
|
||||
catch (NoSuchMessageException ex) {
|
||||
System.out.println("IOException code "+code);
|
||||
throw new JspTagException(getNoSuchMessageExceptionDescription(ex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
super.release();
|
||||
this.arguments = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve the specified message into a concrete message String.
|
||||
* The returned message String should be unescaped.
|
||||
*/
|
||||
protected String resolveMessage() throws JspException, NoSuchMessageException {
|
||||
MessageSource messageSource = getMessageSource();
|
||||
|
||||
// Evaluate the specified MessageSourceResolvable, if any.
|
||||
if (this.message != null) {
|
||||
// We have a given MessageSourceResolvable.
|
||||
return messageSource.getMessage(this.message, getRequestContext().getLocale());
|
||||
}
|
||||
|
||||
if (this.code != null || this.text != null) {
|
||||
// We have a code or default text that we need to resolve.
|
||||
Object[] argumentsArray = resolveArguments(this.arguments);
|
||||
if (!this.nestedArguments.isEmpty()) {
|
||||
argumentsArray = appendArguments(argumentsArray, this.nestedArguments.toArray());
|
||||
}
|
||||
|
||||
if (this.text != null) {
|
||||
// We have a fallback text to consider.
|
||||
String msg = messageSource.getMessage(
|
||||
this.code, argumentsArray, this.text, getRequestContext().getLocale());
|
||||
return (msg != null ? msg : "");
|
||||
}
|
||||
else {
|
||||
// We have no fallback text to consider.
|
||||
return messageSource.getMessage(
|
||||
this.code, argumentsArray, getRequestContext().getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("No resolvable message for code "+code);
|
||||
return argumentSeparator;
|
||||
}
|
||||
|
||||
private Object[] appendArguments(@Nullable Object[] sourceArguments, Object[] additionalArguments) {
|
||||
if (ObjectUtils.isEmpty(sourceArguments)) {
|
||||
return additionalArguments;
|
||||
}
|
||||
Object[] arguments = new Object[sourceArguments.length + additionalArguments.length];
|
||||
System.arraycopy(sourceArguments, 0, arguments, 0, sourceArguments.length);
|
||||
System.arraycopy(additionalArguments, 0, arguments, sourceArguments.length, additionalArguments.length);
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given arguments Object into an arguments array.
|
||||
* @param arguments the specified arguments Object
|
||||
* @return the resolved arguments as array
|
||||
* @throws JspException if argument conversion failed
|
||||
* @see #setArguments
|
||||
*/
|
||||
@Nullable
|
||||
protected Object[] resolveArguments(@Nullable Object arguments) throws JspException {
|
||||
if (arguments instanceof String) {
|
||||
String[] stringArray =
|
||||
StringUtils.delimitedListToStringArray((String) arguments, this.argumentSeparator);
|
||||
if (stringArray.length == 1) {
|
||||
Object argument = stringArray[0];
|
||||
if (argument != null && argument.getClass().isArray()) {
|
||||
return ObjectUtils.toObjectArray(argument);
|
||||
}
|
||||
else {
|
||||
return new Object[] {argument};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return stringArray;
|
||||
}
|
||||
}
|
||||
else if (arguments instanceof Object[]) {
|
||||
return (Object[]) arguments;
|
||||
}
|
||||
else if (arguments instanceof Collection) {
|
||||
return ((Collection<?>) arguments).toArray();
|
||||
}
|
||||
else if (arguments != null) {
|
||||
// Assume a single argument object.
|
||||
return new Object[] {arguments};
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the message to the page.
|
||||
* <p>Can be overridden in subclasses, e.g. for testing purposes.
|
||||
* @param msg the message to write
|
||||
* @throws IOException if writing failed
|
||||
*/
|
||||
protected void writeMessage(String msg) throws IOException {
|
||||
this.pageContext.getOut().write(String.valueOf(msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current RequestContext's application context as MessageSource.
|
||||
*/
|
||||
protected MessageSource getMessageSource() {
|
||||
return getRequestContext().getMessageSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default exception message.
|
||||
*/
|
||||
protected String getNoSuchMessageExceptionDescription(NoSuchMessageException ex) {
|
||||
return ex.getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user