1. 程式人生 > >Spring security實現國際化問題

Spring security實現國際化問題

ryu rep util ets prope name format 自帶 method

這兩天Spring用戶登錄國際化這個問題困擾我好久啊,於昨天晚上終於把它幹掉了。

場景就是我們公司的產品-incopat,需要支持中英文,用戶登錄這塊用的spring自帶的security,需求講的通俗一點就是,中文版提示中文提示信息,英文版提示英文版信息,廢話不多說,見代碼。

首先配置文件

security-config.xml

 1 <beans:bean id="customUsernamePasswordAuthenticationFilter"
 2         class="com.incoshare.base.security.CustomUsernamePasswordAuthenticationFilter"
 3
p:authenticationManager-ref="authenticationManager" 4 p:filterProcessesUrl="/doLogin" p:sessionAuthenticationStrategy-ref="compositeSessionAuthenticationStrategy" 5 p:authenticationSuccessHandler-ref="authenticationSuccessHandler" 6 p:authenticationFailureHandler-ref="authenticationFailureHandler" 7
p:rememberMeServices-ref="rememberMeServices" 8 p:authenticationDetailsSource-ref="customWebAuthenticationDetailsSource"> 9 </beans:bean> 10 11 12 <beans:bean id="messageSource" 13 class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 14
<beans:property name="basename" 15 value="classpath:messages/security/messages" /> 16 </beans:bean>

配置文件只貼了關鍵部分,第一個bean 配置登錄的過濾器,第二個bean加載messages文件(這裏有需要註意的地方如果想引用自己的message文件,建好文件後提供相對地址就可以了,classpath必須要哦!文件命名也是有規則的,message_en 就是下劃線帶上語言簡稱,這個簡稱需要跟網站上切換中英文標示一致),配置文件就這些

下面貼上過濾器代碼

  1 package com.incoshare.base.security;
  2 
  3 import javax.servlet.http.HttpServletRequest;
  4 import javax.servlet.http.HttpServletResponse;
  5 
  6 import com.incoshare.base.util.PropertyUtil;
  7 import com.incoshare.base.util.Utils;
  8 import com.incoshare.incopat4.model.User;
  9 import com.incoshare.incopat4.service.usermanager.UserListService;
 10 import com.incoshare.util.EncryptUtils;
 11 import com.incoshare.util.SingleLoginUtils;
 12 import org.slf4j.Logger;
 13 import org.slf4j.LoggerFactory;
 14 
 15 import org.springframework.beans.factory.annotation.Autowired;
 16 import org.springframework.beans.factory.annotation.Value;
 17 import org.springframework.context.i18n.LocaleContextHolder;
 18 import org.springframework.security.authentication.AuthenticationServiceException;
 19 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 20 import org.springframework.security.core.Authentication;
 21 import org.springframework.security.core.AuthenticationException;
 22 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 23 import org.springframework.util.StringUtils;
 24 import org.springframework.web.servlet.i18n.SessionLocaleResolver;
 25 import org.springframework.web.util.WebUtils;
 26 
 27 import com.incoshare.base.util.RegexUtil;
 28 
 29 import java.text.SimpleDateFormat;
 30 import java.util.Date;
 31 import java.util.Locale;
 32 
 33 public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
 34     
 35     static Logger logger = LoggerFactory
 36             .getLogger(CustomUsernamePasswordAuthenticationFilter.class);
 37 
 38     private boolean postOnly = true;
 39 
 40     private byte[] keyBytes = { 0x21, 0x12, 0x4F, 0x58, (byte) 0x88, 0x09, 0x40, 0x38, 0x74,
 41             0x25, (byte) 0x99, 0x21, (byte) 0xCB, (byte) 0xDD, 0x58, 0x66, 0x77, 0x22, 0x74,
 42             (byte) 0x98, 0x30, 0x40, 0x36, (byte) 0xE2 };
 43     private byte[] keyBytesForSjz = { 0x22, 0x12, 0x4F, 0x58, (byte) 0x88, 0x09, 0x40, 0x38, 0x74,
 44             0x25, (byte) 0x99, 0x21, (byte) 0xCB, (byte) 0xDD, 0x48, 0x66, 0x77, 0x22, 0x74,
 45             (byte) 0x98, 0x30, 0x40, 0x36, (byte) 0xE2 };
 46     @Autowired
 47     UserListService userListService;
 48     @Autowired
 49     PropertyUtil propertyUtil;
 50 
 51     @Override
 52      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
 53         
 54             
 55         String newLocale = request.getParameter("locallangue");
 56         if (newLocale != null) {
 57             Locale locale = StringUtils.parseLocaleString(newLocale);
 58             WebUtils.setSessionAttribute(request,
 59                 SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
 60             LocaleContextHolder.setLocale(locale, true);
 61         }
//這塊代碼就是通過獲取前臺返回的語言編碼,設置到spring的localeContextHolder裏
62 if (postOnly && !request.getMethod().equals("POST")) { 63 throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); 64 } 65 66 String username = obtainUsername(request); 67 String password = obtainPassword(request); 68 69 //集慧智佳用戶登錄 70 String token = request.getParameter("token"); 71 //石家莊單點登錄 72 String tokenForSjz = request.getParameter("tokenForSjz"); 73 if(Utils.isNotNull(token) || Utils.isNotNull(tokenForSjz)){ 74 boolean judge = true; 75 if(Utils.isNull(token)){ 76 judge = false; 77 } 78 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH"); 79 Date date = new Date(); 80 String dateStr = simpleDateFormat.format(date); 81 String decodeToken = ""; 82 String decryptJudge = ""; 83 if(judge){ 84 decodeToken = EncryptUtils.DataDecrypt(keyBytes, token); 85 decryptJudge = token; 86 }else{ 87 decodeToken = EncryptUtils.DataDecrypt(keyBytesForSjz, tokenForSjz); 88 decryptJudge = tokenForSjz; 89 }; 90 if(!decodeToken.equals(decryptJudge.trim()) && decodeToken.equals(dateStr.trim())){ 91 92 User user = userListService.queryUserJhzj(username); 93 if(Utils.isNotNull(user)){ 94 if(Utils.isNotNull(user.getOrganizationId())){ 95 if(judge){ 96 String jhzjOrid=propertyUtil.getContextProperty("jhzjOrid"); 97 String pwd = propertyUtil.getContextProperty("jhzjPassword").trim(); 98 if(user.getOrganizationId().equals(Integer.parseInt(jhzjOrid.trim()))){ 99 password = pwd; 100 } 101 }else{ 102 if(Utils.isNotNull(password)){ 103 String record = password; 104 String orid = propertyUtil.getContextProperty("sjzOrid").trim(); 105 password = EncryptUtils.DataDecrypt(keyBytesForSjz,password); 106 if(record.equals(password) || !String.valueOf(user.getOrganizationId()).equals(orid)){ 107 password = ""; 108 } 109 } 110 } 111 112 } 113 } 114 115 }else{ 116 password = ""; 117 } 118 } 119 120 String tokenForLogin = request.getParameter("tokenForLogin"); 121 if(Utils.isNotNull(tokenForLogin)){ 122 String companyName = request.getParameter("companyName"); 123 String record = password; 124 tokenForLogin = tokenForLogin.replaceAll(" ","+"); 125 password = SingleLoginUtils.decryptPassword(username,password,tokenForLogin,companyName,userListService,propertyUtil,logger); 126 if(Utils.isNull(password)){ 127 logger.info("{}:密碼解密為空。賬號{},沒有解密的密碼:{}",companyName,username,record); 128 } 129 } 130 if (username == null) { 131 username = ""; 132 } 133 134 if (password == null) { 135 password = ""; 136 } 137 138 139 username = username.trim(); 140 141 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); 142 143 if(!StringUtils.isEmpty(request.getParameter("iplogin"))) { 144 username = RegexUtil.getRealIp(request); 145 password=""; 146 authRequest = new IpUserAuthenticationToken(username,password); 147 } 148 149 this.logger.info("user:{},ip:{} trying to login",new Object[]{username,RegexUtil.getRealIp(request)}); 150 151 // Allow subclasses to set the "details" property 152 setDetails(request, authRequest); 153 154 return this.getAuthenticationManager().authenticate(authRequest); 155 } 156 }

這塊先聲明下,代碼不是我寫的,看著很亂很糟糕吧。主要上邊標黃的兩個地方就可以了。

值設置後會通過this.getAuthenticationManager().authenticate(authRequest) 去初始化,喜歡研究源碼的朋友看一跟一下看看

org.springframework.context.i18n.LocaleContextHolder這個類

1 public static LocaleContext getLocaleContext() {
2         LocaleContext localeContext = localeContextHolder.get();
3         if (localeContext == null) {
4             localeContext = inheritableLocaleContextHolder.get();//這裏會把你設置的值放到Spring 容器
5         }
6         return localeContext;
7 }

好了,關鍵的地方都說完了,這幾天搞了這麽久,寫完了也沒多少東西,代碼就是這麽美妙,解決問題的過程是漫長苦惱的,但最終解決有可能就一兩行代碼的事。

關於這一塊有問題的可以隨時溝通。

Spring security實現國際化問題