Browse Source

添加应用秘钥生成接口

huxz 8 năm trước cách đây
mục cha
commit
4bacf93073

+ 39 - 4
sso-manage-console-web/src/components/app/modal/AppModal.vue

@@ -54,9 +54,11 @@
                   <textarea name="publicKey" title="publicKey" rows="3" class="form-control" readonly
                             v-model="appInfo.publicKey"></textarea>
                   <ul class="help-block x-menu">
-                    <li>点击<a class="btn-create" href="javascript:void(0)">生成密钥对</a></li>
+                    <li>点击<a class="btn-create" href="javascript:void(0)" @click="generateSecret()">生成密钥对</a></li>
                     <li>账户中心只保留公钥用于校验,请将私钥配置到程序中,并妥善保管</li>
-                    <li style="display:none"><a class="btn-download" target="_blank" href="/api/secret/private">下载私钥</a></li>
+                    <li v-show="canDownload">
+                      <a class="btn-download" target="_blank" href="/api/app/private//download">下载私钥</a>
+                    </li>
                   </ul>
                 </div>
               </div>
@@ -207,7 +209,8 @@ export default {
     return {
       appVisible: false,
       isAdd: true,
-      appInfo: {}
+      appInfo: {},
+      canDownload: false
     }
   },
   watch: {
@@ -238,9 +241,19 @@ export default {
   },
   methods: {
     saveAppInfo () {
-      if (this.appInfo.type === 'control') {
+      // Validation
+      if (!this.appInfo.uid) {
+        this.showRequiredError({message: '应用唯一标识不能为空'})
+        return 0
+      } else if (!this.appInfo.description) {
+        this.showRequiredError({message: '应用描述不能为空'})
+        return 0
+      } else if (this.appInfo.type === 'control' && !this.appInfo.userControl) {
         this.appInfo.userControl = this.appInfo.userControl || ' '
+        this.showRequiredError({message: '级联应用的唯一标识不能为空'})
+        return 0
       }
+
       const appInfo = _.omit(this.appInfo, 'type')
       console.log(appInfo)
 
@@ -266,6 +279,24 @@ export default {
       const error = response => { this.showAddError({ message: response }) }
 
       axios.delete(`/api/app/${uid}/deleteApp`).then(success).catch(error)
+    },
+    generateSecret () {
+      console.log(1)
+      const success = (publicKey) => {
+        console.log(publicKey)
+        if (publicKey) {
+          this.canDownload = true
+          this.appInfo.publicKey = publicKey
+        } else {
+          this.canDownload = false
+        }
+      }
+      const error = response => {
+        this.canDownload = false
+        this.showAddError({ message: response })
+      }
+
+      axios.get('/api/app/secret//generate').then(success).catch(error)
     }
   },
   computed: {
@@ -281,6 +312,10 @@ export default {
       title: 'Add Failed',
       message: 'Failed to add app info',
       type: 'error'
+    },
+    showRequiredError: {
+      message: 'Required',
+      type: 'error'
     }
   }
 }

+ 15 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/AppManagerController.java

@@ -1,9 +1,12 @@
 package com.uas.sso.sso.backend.api;
 
+import com.uas.sso.common.encrypt.RSA;
 import com.uas.sso.entity.App;
 import com.uas.sso.sso.backend.service.AppService;
 import com.uas.sso.sso.backend.support.ResultBean;
 import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -21,6 +24,8 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping(path = "/api/app")
 public class AppManagerController {
 
+    public static final String SESSION_PRIVATE_KEY = "privateKey";
+
     private final AppService appService;
 
     @Autowired
@@ -54,4 +59,14 @@ public class AppManagerController {
         appService.deleteApp(uid);
         return new ResultBean<>(true);
     }
+
+    @RequestMapping(method = RequestMethod.GET, path = "/secret//generate",
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResultBean<String> generateKey(HttpServletRequest request) throws Exception {
+        Map<String, Object> keyMap = RSA.genKeyPair();
+
+        // Save private key in session for downloading
+        request.getSession().setAttribute(SESSION_PRIVATE_KEY, RSA.getPrivateKey(keyMap));
+        return new ResultBean<>(RSA.getPublicKey(keyMap));
+    }
 }

+ 57 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/web/AppController.java

@@ -0,0 +1,57 @@
+package com.uas.sso.sso.backend.web;
+
+import com.uas.sso.sso.backend.api.AppManagerController;
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * An implementation class for app.
+ *
+ * @author huxz
+ */
+@Controller
+@RequestMapping(path = "/api/app")
+public class AppController {
+
+    @RequestMapping(method = RequestMethod.GET, path = "/private//download",
+            produces = MediaType.TEXT_HTML_VALUE)
+    public ResponseEntity<byte[]> downloadKey(HttpServletRequest request,
+            HttpServletResponse response) throws IOException {
+        String privateKey = (String) request.getSession()
+                .getAttribute(AppManagerController.SESSION_PRIVATE_KEY);
+
+        if (StringUtils.isEmpty(privateKey)) {
+            printErrors(response, "未找到密钥,请重新生成");
+            return null;
+        }
+        // Avoid download private key repeatedly
+        request.getSession().removeAttribute(AppManagerController.SESSION_PRIVATE_KEY);
+        return outputStream("privateKey.txt", privateKey.getBytes());
+    }
+
+    private ResponseEntity<byte[]> outputStream(String fileName, byte[] bytes) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+        headers.setContentDispositionFormData("attachment", fileName);
+        return new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
+    }
+
+    private void printErrors(HttpServletResponse response,
+            String error) throws IOException {
+        response.addHeader("Content-Type", "text/html; charset=UTF-8");
+        PrintWriter printWriter = response.getWriter();
+        printWriter.append(error);
+        printWriter.flush();
+        printWriter.close();
+    }
+}