浏览代码

image change to base 64

MaxKey 3 年之前
父节点
当前提交
c810401040
共有 27 个文件被更改,包括 242 次插入43 次删除
  1. 142 0
      maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaBase64Endpoint.java
  2. 18 1
      maxkey-core/src/main/java/org/maxkey/entity/UserInfo.java
  3. 18 1
      maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java
  4. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/AppListController.java
  5. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ProfileController.java
  6. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/main/appConfigList.ftl
  7. 2 2
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/main/appList.ftl
  8. 1 1
      maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/profile/myProfile.ftl
  9. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ApplicationsController.java
  10. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/BasicDetailsController.java
  11. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/CasDetailsController.java
  12. 1 2
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ExtendApiDetailsController.java
  13. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/FormBasedDetailsController.java
  14. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/JwtDetailsController.java
  15. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/OAuth20DetailsController.java
  16. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/SAML20DetailsController.java
  17. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/TokenBasedDetailsController.java
  18. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/GroupPrivilegesController.java
  19. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/UserInfoController.java
  20. 1 1
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appUpdateCommon.ftl
  21. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appsList.ftl
  22. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/selectAppsList.ftl
  23. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/groupapp/addGroupAppsList.ftl
  24. 2 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/groupapp/groupAppsList.ftl
  25. 8 2
      maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/userinfo/userUpdate.ftl
  26. 0 8
      maxkey-webs/maxkey-web-resources/src/main/resources/static/css/base.css
  27. 28 2
      maxkey-webs/maxkey-web-resources/src/main/resources/static/javascript/platform.common.js

+ 142 - 0
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaBase64Endpoint.java

@@ -0,0 +1,142 @@
+/*
+ * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * 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 org.maxkey.web.contorller;
+
+import com.google.code.kaptcha.Producer;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+import javax.imageio.ImageIO;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+
+/**
+ * ImageCaptchaEndpoint  Producer captcha.
+ * @author Crystal.Sea
+ *
+ */
+@Controller
+public class ImageCaptchaBase64Endpoint {
+    private static final Logger _logger = LoggerFactory.getLogger(ImageCaptchaBase64Endpoint.class);
+
+    public static final	String IMAGE_GIF 			= "image/gif";
+    
+    public static final	String KAPTCHA_SESSION_KEY 	= "kaptcha_session_key";
+    
+    @Autowired
+    private Producer captchaProducer;
+
+    /**
+     * captcha image Producer.
+     * 
+     * @param request HttpServletRequest
+     * @param response HttpServletResponse
+     */
+    @RequestMapping(value = "/captcha/base64")
+    public void captchaHandleRequest(HttpServletRequest  request, 
+    								 HttpServletResponse response, 
+    								 @RequestParam(value="captcha",required=false,defaultValue="text") String captchaType) {
+        try {
+        	
+            String kaptchaText = captchaProducer.createText();
+            if (captchaType.equalsIgnoreCase("Arithmetic")) {
+                Integer intParamA = Integer.valueOf(kaptchaText.substring(0, 1));
+                Integer intParamB = Integer.valueOf(kaptchaText.substring(1, 2));
+                Integer calculateValue = 0;
+                if ((intParamA > intParamB) && ((intParamA + intParamB) % 5 > 3)) {
+                    calculateValue = intParamA - intParamB;
+                    kaptchaText = intParamA + "-" + intParamB + "=?";
+                } else {
+                    calculateValue = intParamA + intParamB;
+                    kaptchaText = intParamA + "+" + intParamB + "=?";
+                }
+                _logger.trace("Sesssion id " + request.getSession().getId() 
+                        + " , Arithmetic calculate Value is " + calculateValue);
+                request.getSession().setAttribute(
+                        KAPTCHA_SESSION_KEY, calculateValue + "");
+            } else {
+                // store the text in the session
+                request.getSession().setAttribute(KAPTCHA_SESSION_KEY, kaptchaText);
+            }
+            _logger.trace("Sesssion id " + request.getSession().getId() 
+                                + " , Captcha Text is " + kaptchaText);
+           
+            // create the image with the text
+            BufferedImage bufferedImage = captchaProducer.createImage(kaptchaText);
+            producerImage(request,response,bufferedImage);
+        } catch (Exception e) {
+            _logger.error("captcha Producer Error " + e.getMessage());
+        }
+    }
+
+    /**
+     * producerImage.
+     * @param request HttpServletRequest
+     * @param response HttpServletResponse
+     * @param bufferedImage BufferedImage
+     * @throws IOException error
+     */
+    public static void producerImage(HttpServletRequest request, 
+                              HttpServletResponse response,
+                              BufferedImage bufferedImage) throws IOException {
+        // Set to expire far in the past.
+        response.setDateHeader("Expires", 0);
+        // Set standard HTTP/1.1 no-cache headers.
+        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
+        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
+        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
+        // Set standard HTTP/1.0 no-cache header.
+        response.setHeader("Pragma", "no-cache");
+        // return a jpeg/gif
+        //response.setContentType(IMAGE_GIF);
+        _logger.trace("create the image");
+        // create the image
+        if (bufferedImage != null) {
+            ServletOutputStream out = response.getOutputStream();
+            // write the data out
+            ByteArrayOutputStream stream = new ByteArrayOutputStream();
+			ImageIO.write(bufferedImage, "png", stream);
+			String b64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(stream.toByteArray());
+            out.print(b64Image);
+            _logger.debug("b64Image {}" , b64Image);
+            stream.close();
+            try {
+                out.flush();
+            } finally {
+                out.close();
+            }
+        }
+    }
+
+	public void setCaptchaProducer(Producer captchaProducer) {
+        this.captchaProducer = captchaProducer;
+    }
+
+
+}

+ 18 - 1
maxkey-core/src/main/java/org/maxkey/entity/UserInfo.java

@@ -19,6 +19,7 @@ package org.maxkey.entity;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import java.io.IOException;
+import java.util.Base64;
 import java.util.HashMap;
 import java.util.List;
 
@@ -101,6 +102,7 @@ public class UserInfo extends JpaBaseEntity {
     @JsonIgnore
     @Column
     protected byte[] picture;
+    protected String pictureBase64;
     @JsonIgnore
     protected MultipartFile pictureFile;
     @Column
@@ -399,7 +401,22 @@ public class UserInfo extends JpaBaseEntity {
         return picture;
     }
 
-    /**
+    public String getPictureBase64() {
+		return pictureBase64;
+	}
+
+	public void setPictureBase64(String pictureBase64) {
+		this.pictureBase64 = pictureBase64;
+	}
+
+	public void transPictureBase64() {
+		if(picture != null) {
+			this.pictureBase64 = "data:image/png;base64," + 
+					Base64.getEncoder().encodeToString(picture);
+		}
+	}
+	
+	/**
      * @return the protectedAppsMap
      */
     public HashMap<String, String> getProtectedAppsMap() {

+ 18 - 1
maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java

@@ -18,6 +18,7 @@
 package org.maxkey.entity.apps;
 
 import java.io.Serializable;
+import java.util.Base64;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -78,6 +79,7 @@ public class Apps extends JpaBaseEntity implements Serializable {
      */
     @Column
     private byte[] icon;
+    private String iconBase64;
     private MultipartFile iconFile;
     @Column
     private int visible;
@@ -270,7 +272,22 @@ public class Apps extends JpaBaseEntity implements Serializable {
         this.icon = icon;
     }
 
-    /**
+    public String getIconBase64() {
+		return iconBase64;
+	}
+
+	public void setIconBase64(String iconBase64) {
+		this.iconBase64 = iconBase64;
+	}
+	
+	public void transIconBase64() {
+		if(icon !=null) {
+			this.iconBase64 = "data:image/png;base64," + 
+					Base64.getEncoder().encodeToString(icon);
+		}
+	}
+
+	/**
      * @return the iconFile
      */
     public MultipartFile getIconFile() {

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/AppListController.java

@@ -96,7 +96,7 @@ public class AppListController {
         userApplications.setInstId(WebContext.getUserInfo().getInstId());
         List<UserApps> appList = appsService.queryMyApps(userApplications);
         for (UserApps app : appList) {
-            WebContext.setAttribute(app.getId(), app.getIcon());
+        	app.transIconBase64();
         }
 
         return appList;

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ProfileController.java

@@ -47,7 +47,7 @@ public class ProfileController {
     public ModelAndView forwardBasic() {
         ModelAndView modelAndView = new ModelAndView("profile/myProfile");
         UserInfo userInfo = userInfoService.findByUsername(WebContext.getUserInfo().getUsername());
-        WebContext.getSession().setAttribute(userInfo.getId(), userInfo.getPicture());
+        userInfo.transPictureBase64();
 
         //  HashMap<String,Object>extraAttributeMap=new HashMap<String,Object>();
         //  extraAttributeMap=(HashMap<String,Object>)JsonUtils.json2Object(userInfo.getExtraAttribute(),extraAttributeMap);

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/main/appConfigList.ftl

@@ -34,7 +34,7 @@
 	<tr>
 		<td>${app_index +1 }</td>
 		<td>
-			<img src="<@base/>/image/${app.id}" title="${app.name}" width="65px" height="65px"  style="border:0;"/>
+			<img src="${app.iconBase64}" title="${app.name}" width="65px" height="65px"  style="border:0;"/>
 		</td>
 		<td>${app.name}</td>
 		<td>

+ 2 - 2
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/main/appList.ftl

@@ -31,7 +31,7 @@
 	  							<#if "IDP"==app.inducer>
 	  								href="<@base/>/authz/${app.id}"
 	  							</#if>  >
-	  							<img src="<@base/>/image/${app.id}" title="${app.name}" class="appListimage"/>
+	  							<img src="${app.iconBase64}" title="${app.name}" class="appListimage"/>
 	  						</a><br>
 	  						${app.name}
 	  					</td></tr>
@@ -76,7 +76,7 @@
 						href="<@base/>/authz/${app.id}"
 					</#if>
 					 target="_blank" title="${app.name}" >
-					<img src="<@base/>/image/${app.id}" title="${app.name}" class="appListimage"/>
+					<img src="${app.iconBase64}" title="${app.name}" class="appListimage"/>
 				</a>
 		</td>
 		<td style="">${app.name}</td>

+ 1 - 1
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/profile/myProfile.ftl

@@ -314,7 +314,7 @@
 					<td>
 						<img id="picture" width="150px" height="215px" 
 						<#if  model.picture ?? >
-						    src="<@base/>/image/${model.id}" />
+						    src="${model.pictureBase64}" />
 						<#else>
 							src="<@base/>/static/images/uploadimage.jpg" /> 
 						</#if>

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ApplicationsController.java

@@ -77,7 +77,7 @@ public class ApplicationsController extends BaseAppContorller {
 		JpaPageResults<Apps> apps=appsService.queryPageResults(applications);
 		if(apps!=null&&apps.getRows()!=null){
 			for (Apps app : apps.getRows()){
-				WebContext.setAttribute(app.getId(), app.getIcon());
+				app.transIconBase64();
 			}
 		}
 		return apps;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/BasicDetailsController.java

@@ -72,7 +72,7 @@ public class BasicDetailsController  extends BaseAppContorller {
 		ModelAndView modelAndView=new ModelAndView("apps/basic/appUpdate");
 		Apps appDetails=appsService.get(id);
 		super.decoderSecret(appDetails);
-		WebContext.setAttribute(appDetails.getId(), appDetails.getIcon());
+		appDetails.transIconBase64();
 		modelAndView.addObject("model",appDetails);
 		return modelAndView;
 	}

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/CasDetailsController.java

@@ -76,8 +76,8 @@ public class CasDetailsController  extends BaseAppContorller {
 		ModelAndView modelAndView=new ModelAndView("apps/cas/appUpdate");
 		AppsCasDetails casDetails=casDetailsService.getAppDetails(id , false);
 		super.decoderSecret(casDetails);
-		WebContext.setAttribute(casDetails.getId(), casDetails.getIcon());
-
+		casDetails.transIconBase64();
+		
 		modelAndView.addObject("model",casDetails);
 		return modelAndView;
 	}

+ 1 - 2
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/ExtendApiDetailsController.java

@@ -76,8 +76,7 @@ public class ExtendApiDetailsController  extends BaseAppContorller {
 		super.decoderSecret(application);
 		AppsExtendApiDetails extendApiDetails=new AppsExtendApiDetails();
 		BeanUtils.copyProperties(application, extendApiDetails);
-		
-		WebContext.setAttribute(extendApiDetails.getId(), extendApiDetails.getIcon());
+		extendApiDetails.transIconBase64();
 
 		modelAndView.addObject("model",extendApiDetails);
 		return modelAndView;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/FormBasedDetailsController.java

@@ -80,7 +80,7 @@ public class FormBasedDetailsController  extends BaseAppContorller {
 		AppsFormBasedDetails formBasedDetails=formBasedDetailsService.getAppDetails(id , false);
 		decoderSecret(formBasedDetails);
 		decoderSharedPassword(formBasedDetails);
-		WebContext.setAttribute(formBasedDetails.getId(), formBasedDetails.getIcon());
+		formBasedDetails.transIconBase64();
 
 		modelAndView.addObject("model",formBasedDetails);
 		return modelAndView;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/JwtDetailsController.java

@@ -79,7 +79,7 @@ public class JwtDetailsController  extends BaseAppContorller {
 		ModelAndView modelAndView=new ModelAndView("apps/jwt/appUpdate");
 		AppsJwtDetails jwtDetails=jwtDetailsService.getAppDetails(id , false);
 		decoderSecret(jwtDetails);
-		WebContext.setAttribute(jwtDetails.getId(), jwtDetails.getIcon());
+		jwtDetails.transIconBase64();
 
 		modelAndView.addObject("model",jwtDetails);
 		return modelAndView;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/OAuth20DetailsController.java

@@ -94,7 +94,7 @@ public class OAuth20DetailsController  extends BaseAppContorller {
 		oauth20Details.setSecret(application.getSecret());
 		oauth20Details.setClientSecret(application.getSecret());
 		_logger.debug("forwardUpdate "+oauth20Details);
-		WebContext.setAttribute(oauth20Details.getId(), oauth20Details.getIcon());
+		oauth20Details.transIconBase64();
 		modelAndView.addObject("model",oauth20Details);
 		return modelAndView;
 	}

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/SAML20DetailsController.java

@@ -106,7 +106,7 @@ public class SAML20DetailsController   extends BaseAppContorller {
 		ModelAndView modelAndView=new ModelAndView("apps/saml20/appUpdate");
 		AppsSAML20Details saml20Details=saml20DetailsService.getAppDetails(id , false);
 		decoderSecret(saml20Details);
-		WebContext.setAttribute(saml20Details.getId(), saml20Details.getIcon());
+		saml20Details.transIconBase64();
 		modelAndView.addObject("model",saml20Details);
 		modelAndView.addObject("authzURI",applicationConfig.getAuthzUri());
 		return modelAndView;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/apps/contorller/TokenBasedDetailsController.java

@@ -83,7 +83,7 @@ public class TokenBasedDetailsController  extends BaseAppContorller {
 		decoderSecret(tokenBasedDetails);
 		String algorithmKey=passwordReciprocal.decoder(tokenBasedDetails.getAlgorithmKey());
 		tokenBasedDetails.setAlgorithmKey(algorithmKey);
-		WebContext.setAttribute(tokenBasedDetails.getId(), tokenBasedDetails.getIcon());
+		tokenBasedDetails.transIconBase64();
 
 		modelAndView.addObject("model",tokenBasedDetails);
 		return modelAndView;

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/GroupPrivilegesController.java

@@ -62,7 +62,7 @@ public class GroupPrivilegesController {
 
 		if(groupPrivileges!=null&&groupPrivileges.getRows()!=null){
 			for (Apps app : groupPrivileges.getRows()){
-				WebContext.setAttribute(app.getId(), app.getIcon());
+				app.transIconBase64();
 			}
 		}
 		return groupPrivileges;
@@ -86,7 +86,7 @@ public class GroupPrivilegesController {
 
 		if(groupPrivileges!=null&&groupPrivileges.getRows()!=null){
 			for (Apps app : groupPrivileges.getRows()){
-				WebContext.setAttribute(app.getId(), app.getIcon());
+				app.transIconBase64();
 			}
 		}
 		return groupPrivileges;

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/java/org/maxkey/web/contorller/UserInfoController.java

@@ -145,7 +145,7 @@ public class UserInfoController {
 		ModelAndView modelAndView=new ModelAndView("/userinfo/userUpdate");
 		UserInfo userInfo=userInfoService.get(id);
 		if(userInfo.getPicture()!=null){
-			WebContext.getSession().setAttribute(userInfo.getId(), userInfo.getPicture());
+			userInfo.transPictureBase64();
 		}
 		
 		modelAndView.addObject("model", userInfo);

+ 1 - 1
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appUpdateCommon.ftl

@@ -33,7 +33,7 @@
          </td>
         <th><@locale code="apps.icon"/></th>
         <td>
-            <img id="iconFileImg" height='30' src='<@base/>/image/${model.id!}'/>
+            <img id="iconFileImg" height='30' src='${model.iconBase64!}'/>
         </td>
       </tr>
       <tr>

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/appsList.ftl

@@ -5,7 +5,7 @@
 	<#include  "../layout/common.cssjs.ftl"/>
 <script type="text/javascript">				
 	function iconFormatter(value, row, index){
-  			return "<img height='30' border='0px' src='<@base/>/image/"+value+"'/>";
+  			return "<img height='30' border='0px' src='"+value+"'";
 	};
 	
 	function vendorFormatter(value, options, rData){
@@ -198,7 +198,7 @@
                 <tr>
                     <th data-checkbox="true"></th>
                     <th data-sortable="true" data-field="id"   data-visible="false">Id</th>
-                    <th data-field="id" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
+                    <th data-field="iconBase64" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
                     <th data-field="name"><@locale code="apps.name"/></th>
                     <th data-field="protocol"><@locale code="apps.protocol"/></th>
                     <th data-field="category"><@locale code="apps.category"/></th>

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/apps/selectAppsList.ftl

@@ -12,7 +12,7 @@
   
 <script type="text/javascript">				
 	function iconFormatter(value, row, index){
-  			return "<img height='30' border='0px' src='<@base/>/image/"+value+"'/>";
+  			return "<img height='30' border='0px' src='"+value+"'";
 	};
 
 	$(function () {
@@ -71,7 +71,7 @@
 			<tr>
 				<th data-checkbox="true"></th>
 				<th data-sortable="true" data-field="id"   data-visible="false">Id</th>
-				<th data-field="id" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
+				<th data-field="iconBase64" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
 				<th data-field="name"><@locale code="apps.name"/></th>
 				<th data-field="protocol"  data-visible="false"><@locale code="apps.protocol"/></th>
 				<th data-field="category"><@locale code="apps.category"/></th>

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/groupapp/addGroupAppsList.ftl

@@ -15,7 +15,7 @@
 			}
 			
 			function iconFormatter(value, row, index){
-  			return "<img height='30' border='0px' src='<@base/>/image/"+value+"'/>";
+  			   return "<img height='30' border='0px' src='"+value+"'";
 			};
 		   	
 			$(function () {
@@ -115,7 +115,7 @@
 			<tr>
 				<th data-checkbox="true"></th>
 				<th data-sortable="true" data-field="id"   data-visible="false">Id</th>
-				<th data-field="id" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
+				<th data-field="iconBase64" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
 				<th data-field="name"><@locale code="apps.name"/></th>
 				<th data-field="protocol"  data-visible="false"><@locale code="apps.protocol"/></th>
 				<th data-field="category"><@locale code="apps.category"/></th>

+ 2 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/groupapp/groupAppsList.ftl

@@ -7,7 +7,7 @@
 <script type="text/javascript">	
 	
 	function iconFormatter(value, row, index){
-  			return "<img height='30' border='0px' src='<@base/>/image/"+value+"'/>";
+  			return "<img height='30' border='0px' src='"+value+"'";
 	};
    	
 	$(function () {
@@ -129,7 +129,7 @@
 			<tr>
 				<th data-checkbox="true"></th>
 				<th data-sortable="true" data-field="id"   data-visible="false">Id</th>
-				<th data-field="id" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
+				<th data-field="iconBase64" data-formatter="iconFormatter"><@locale code="apps.icon"/></th>
 				<th data-field="name"><@locale code="apps.name"/></th>
 				<th data-field="protocol"  data-visible="false"><@locale code="apps.protocol"/></th>
 				<th data-field="category"><@locale code="apps.category"/></th>

+ 8 - 2
maxkey-webs/maxkey-web-mgt/src/main/resources/templates/views/userinfo/userUpdate.ftl

@@ -109,8 +109,14 @@
 		</td>
 		<td rowspan="3"><@locale code="userinfo.picture" /></td>
 		<td rowspan="3">
-			<img id="picture" width="150px" height="150px" src="<@base/>/static/images/uploadimage.jpg" />
-			<input type="file" id="pictureFile" name="pictureFile" style="display:none" />
+		  <img id="picture" width="150px" height="150px" 
+		  <#if  model.pictureBase64 ?? >
+                src="${model.pictureBase64}" 
+          <#else>
+                src="<@base/>/static/images/uploadimage.jpg"
+          </#if>            
+		  />
+		  <input type="file" id="pictureFile" name="pictureFile" style="display:none" />
 					</td>
 	</tr>
 	<tr>

+ 0 - 8
maxkey-webs/maxkey-web-resources/src/main/resources/static/css/base.css

@@ -288,14 +288,6 @@ body{
 	font-weight: bold;	
 }
 
-
-
-#j_captchaimg{
-	width:70px;
-	height: 35px;
-	vertical-align: top;
-}
-
 .login_form_table #j_captchaimg{
     width: 100px;
     height: 40px;

+ 28 - 2
maxkey-webs/maxkey-web-resources/src/main/resources/static/javascript/platform.common.js

@@ -29,12 +29,38 @@ $(function(){
         });
     });
     
-    var captchaImageUrl = $('.captcha-image').attr("src");
+    
+    //captcha-image
+    if($('.captcha-image').length > 0){
+        $('.captcha-image').attr("url",
+            $('.captcha-image').attr("src").indexOf("?")>-1?
+            $('.captcha-image').attr("src"):$('.captcha-image').attr("src")+"?data=img");
+    }
 	//on captcha image click ,new a captcha code
 	$('.captcha-image').click(function () {//
-		$(this).attr("src", captchaImageUrl+"&"+(new Date()).getTime()); 
+		$(this).attr("src", $(this).attr("url")+"&"+(new Date()).getTime()); 
 	});
     
+    //captcha-imageb64
+    if($('.captcha-imageb64').length > 0){
+        $('.captcha-imageb64').attr("url",
+            $('.captcha-imageb64').attr("src").indexOf("?")>-1?
+            $('.captcha-imageb64').attr("src"):$('.captcha-imageb64').attr("src")+"?data=img");
+    }
+    $(".captcha-imageb64").each(function(){
+        var _this = this;
+        $.get($(this).attr("url")+"&"+(new Date()).getTime(), function(result){
+            $(_this).attr("src",result);
+        });
+    });
+    //on captcha image click ,new a captcha code
+    $('.captcha-imageb64').click(function () {//
+        var _this = this;
+        $.get($(this).attr("url")+"&"+(new Date()).getTime(), function(result){
+            $(_this).attr("src",result);
+        });
+    });
+    
     //passwdeye
     $('.passwdeye').click(function () {//
         if($(this).hasClass("fa-eye-slash")){