Commit c897835e authored by panyf's avatar panyf
Browse files

[CP]修改返回错误信息异常问题,增加jwt鉴权功能

parent 5c58920d
......@@ -46,6 +46,11 @@
<version>3.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<build>
......
package com.example.compileproxyserver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
......@@ -25,10 +27,39 @@ public class FileUploadController {
private static final String UPLOAD_DIR = "/home/devicemanager/programs";
private static final String TARGET_FILE = "radarcal.cc";
private static final String USER_NAME = "cdProxy";
private static final String USER_PASSWORD = "cdProxy_zed";
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam("username") String username, @RequestParam("password") String password) {
System.out.println("username: " + username + " password: " + password);
if (USER_NAME.equals(username) && USER_PASSWORD.equals(password)) {
String token = new JwtUtil().generateToken(username);
//test
System.out.println("token: " + token + " username: " + username + " password: " + password + "extractname: " + jwtUtil.extractUsername(token));
return ResponseEntity.ok(new JwtUtil.AuthResponse(token).getToken());
} else {
return ResponseEntity.status(401).body("Invalid username or password");
}
}
@PostMapping("/upload")
public ResponseEntity<Object> uploadFile(@RequestParam("file") MultipartFile file) {
public ResponseEntity<Object> uploadFile(@RequestHeader("Authorization") String authorizationHeader,
@RequestParam("file") MultipartFile file) {
try {
String token = authorizationHeader.replace("Bearer ", "");
System.out.println("token: " + token + " username: " + "extractname: " + jwtUtil.extractUsername(token));
String username = jwtUtil.extractUsername(token);
if(jwtUtil.validateToken(token, username)){
System.out.println("Token is valid");
return ResponseEntity.status(401).body("token错误,请刷新页面重新登录");
}
// 创建上传目录
File uploadDir = new File(UPLOAD_DIR);
if (!uploadDir.exists()) {
......@@ -73,6 +104,8 @@ public class FileUploadController {
return ResponseEntity.status(500)
.contentType(MediaType.TEXT_PLAIN)
.body(e.getMessage());
} catch (RuntimeException e) {
return ResponseEntity.status(401).body(e.getMessage());
}
}
......@@ -87,13 +120,11 @@ public class FileUploadController {
Process rmMkdirProcess = rmMkdirBuilder.start();
int rmMkdirExitCode = rmMkdirProcess.waitFor();
// 捕获并打印 rm -rf build && mkdir build 的输出
logProcessOutput(rmMkdirProcess);
if (rmMkdirExitCode != 0) {
// 获取错误流并读取错误信息
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(rmMkdirProcess.getErrorStream()))) {
String errorLog = errorReader.lines().collect(Collectors.joining(" "));
String errorLog = errorReader.lines().collect(Collectors.joining("\n"));
System.out.println("Failed to clean and create build directory: " + errorLog);
return new PublishResult(false, "Failed to clean and create build directory: " + errorLog, publishDir);
}
}
......@@ -104,50 +135,18 @@ public class FileUploadController {
Process cmakeMakeProcess = cmakeMakeBuilder.start();
int cmakeMakeExitCode = cmakeMakeProcess.waitFor();
// 捕获并打印 cmake 和 make 的输出
String outputLog = logProcessOutput(cmakeMakeProcess);
if (cmakeMakeExitCode != 0) {
// 获取错误流并读取错误信息
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(cmakeMakeProcess.getErrorStream()))) {
String errorLog = errorReader.lines().collect(Collectors.joining(" "));
return new PublishResult(false, "CMake or Make failed: " + outputLog + " Error: " + errorLog, publishDir);
String errorLog = errorReader.lines().collect(Collectors.joining("\n"));
return new PublishResult(false, "CMake or Make failed: " + " Error: " + errorLog, publishDir);
}
}
return new PublishResult(true, "Build succeeded", publishDir);
}
/**
* 捕获并打印进程的标准输出和错误输出。
*
* @param process 要捕获输出的进程
* @return 标准输出的日志内容
*/
private String logProcessOutput(Process process) throws IOException {
StringBuilder outputLog = new StringBuilder();
// 捕获标准输出
try (BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
System.out.println("Standard Output:");
while ((line = outputReader.readLine()) != null) {
System.out.println(line); // 打印到控制台
}
}
// 捕获错误输出
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
System.out.println("Error Output:");
while ((line = errorReader.readLine()) != null) {
System.err.println(line); // 打印到控制台(红色字体)
}
}
return outputLog.toString();
}
private Path findPublishedFile(Path publishDir) {
File[] files = publishDir.toFile().listFiles();
......
package com.example.compileproxyserver;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private final String SECRET_KEY = "ZEDzedZeDZEdzEDzeDtechTechTEchTEChTECHsecretSECRET";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateToken(String token, String username) {
try {
final String extractedUsername = extractUsername(token);
return (extractedUsername.equals(username) && !isTokenExpired(token));
} catch (JwtException | IllegalArgumentException e) {
throw new RuntimeException("Expired or invalid JWT token");
}
}
private boolean isTokenExpired(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration().before(new Date());
}
public class AuthRequest {
private String username;
private String password;
// Getters and setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
static class AuthResponse {
private String token;
public AuthResponse(String token) {
this.token = token;
}
// Getter
public String getToken() {
return token;
}
}
}
#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}.upload-container[data-v-9955520a]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh}
\ No newline at end of file
(function(){"use strict";var e={6653:function(e,t,s){var r=s(5471),o=function(){var e=this,t=e._self._c;return t("div",{attrs:{id:"app"}},[t("router-view")],1)},n=[],i={data(){return{}},methods:{},mounted(){}},a=i,l=s(1656),u=(0,l.A)(a,o,n,!1,null,null,null),c=u.exports,d=s(173),g=function(){var e=this,t=e._self._c;return t("div",{staticClass:"upload-container"},[t("el-dialog",{attrs:{visible:e.loginDialogVisible,title:"登录"},on:{"update:visible":function(t){e.loginDialogVisible=t}}},[t("el-form",{on:{submit:function(t){return t.preventDefault(),e.handleLogin.apply(null,arguments)}}},[t("el-form-item",{attrs:{label:"用户名"}},[t("el-input",{model:{value:e.loginForm.username,callback:function(t){e.$set(e.loginForm,"username",t)},expression:"loginForm.username"}})],1),t("el-form-item",{attrs:{label:"密码"}},[t("el-input",{attrs:{type:"password"},model:{value:e.loginForm.password,callback:function(t){e.$set(e.loginForm,"password",t)},expression:"loginForm.password"}})],1),t("el-button",{attrs:{type:"primary","native-type":"submit"}},[e._v("登录")])],1)],1),e.isLoggedIn?t("el-upload",{ref:"uploadRef",attrs:{action:e.uploadUrl,"auto-upload":!1,"on-change":e.handleFileChange,"file-list":e.fileList,accept:".cc",multiple:!1},scopedSlots:e._u([{key:"trigger",fn:function(){return[t("el-button",{attrs:{size:"small",type:"primary"}},[e._v("选取文件")])]},proxy:!0}],null,!1,2040363866)},[t("el-button",{staticStyle:{"margin-left":"10px"},attrs:{size:"small",type:"success",disabled:e.isUploading},on:{click:e.uploadFile}},[e._v(" 上传并编译 ")])],1):e._e(),e.isLoggedIn&&e.isUploading?t("el-progress",{staticClass:"mt-4",attrs:{percentage:e.progressPercentage,status:e.progressStatus,"stroke-width":10,"show-info":!1}}):e._e(),e.isLoggedIn&&e.isSuccess?t("el-alert",{staticClass:"mt-4",attrs:{title:"编译成功!",type:"success","show-icon":""}}):e._e(),e.isLoggedIn&&e.showErrorMessage?t("el-alert",{staticClass:"mt-4",attrs:{title:"发布错误信息",type:"error",closable:!1}},[e._v(" "+e._s(e.errorMessage)+" ")]):e._e(),e.isLoggedIn&&e.isDownloadAvailable?t("el-button",{staticClass:"mt-4",attrs:{size:"small",type:"primary"},on:{click:e.downloadFile}},[e._v(" 下载标定程序 ")]):e._e()],1)},p=[],h=(s(4603),s(7566),s(8721),s(4335)),f={data(){return{loginDialogVisible:!0,loginForm:{username:"",password:""},isLoggedIn:!1,uploadUrl:"/upload",fileList:[],selectedFile:null,downloadUrl:null,downloadFileName:"radarcal",errorMessage:"",showErrorMessage:!1,isUploading:!1,progressPercentage:0,progressStatus:"",isSuccess:!1,isDownloadAvailable:!1,progressInterval:null}},methods:{handleLogin(){h.A.post("/login",this.loginForm).then((e=>{const t=e.data;localStorage.setItem("token",t),this.isLoggedIn=!0,this.loginDialogVisible=!1,this.$message.success("登录成功")})).catch((e=>{this.$message.error("登录失败,请检查用户名和密码")}))},handleFileChange(e){this.selectedFile=e.raw,this.fileList=[e]},async uploadFile(){if(this.selectedFile){this.errorMessage="",this.showErrorMessage=!1,this.isSuccess=!1,this.isUploading=!0,this.progressPercentage=0,this.progressStatus="",this.progressInterval=setInterval((()=>{this.progressPercentage<100?this.progressPercentage+=1:clearInterval(this.progressInterval)}),1200);try{const e=new FormData;e.append("file",this.selectedFile);const t=await fetch(this.uploadUrl,{method:"POST",headers:{Authorization:`Bearer ${localStorage.getItem("token")}`},body:e});if(clearInterval(this.progressInterval),t.ok){const e=await t.blob();this.downloadUrl=window.URL.createObjectURL(e),this.isDownloadAvailable=!0,this.isSuccess=!0,this.progressPercentage=100,this.progressStatus="success",this.$message.success("编译成功!")}else{const e=await t.text();this.errorMessage=e,this.showErrorMessage=!0,this.progressStatus="error",401===t.status&&(this.$message.error("登录已过期,请重新登录"),this.isLoggedIn=!1,this.loginDialogVisible=!0)}}catch(e){clearInterval(this.progressInterval),console.error("发生错误:",e),this.errorMessage="发生错误,请重试",this.showErrorMessage=!0,this.progressStatus="error",e.response&&401===e.response.status&&(this.$message.error("登录已过期,请重新登录"),this.isLoggedIn=!1,this.loginDialogVisible=!0)}finally{this.isUploading=!1}}else this.$message.error("请选择一个文件")},downloadFile(){if(this.downloadUrl){const e=document.createElement("a");e.href=this.downloadUrl,e.download=this.downloadFileName,document.body.appendChild(e),e.click(),document.body.removeChild(e)}}}},m=f,v=(0,l.A)(m,g,p,!1,null,"9955520a",null),b=v.exports;r["default"].use(d.Ay);const w=[{path:"/",name:"root",redirect:"/upload"},{path:"/upload",name:"upload",component:b}],y=new d.Ay({mode:"history",base:"/",routes:w});var F=y,I=s(1052),S=s.n(I),_=s(9952);r["default"].config.productionTip=!1,r["default"].use(S()),r["default"].use(S(),{locale:_["default"]}),new r["default"]({router:F,render:e=>e(c)}).$mount("#app")}},t={};function s(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={id:r,loaded:!1,exports:{}};return e[r].call(n.exports,n,n.exports,s),n.loaded=!0,n.exports}s.m=e,function(){s.amdO={}}(),function(){var e=[];s.O=function(t,r,o,n){if(!r){var i=1/0;for(c=0;c<e.length;c++){r=e[c][0],o=e[c][1],n=e[c][2];for(var a=!0,l=0;l<r.length;l++)(!1&n||i>=n)&&Object.keys(s.O).every((function(e){return s.O[e](r[l])}))?r.splice(l--,1):(a=!1,n<i&&(i=n));if(a){e.splice(c--,1);var u=o();void 0!==u&&(t=u)}}return t}n=n||0;for(var c=e.length;c>0&&e[c-1][2]>n;c--)e[c]=e[c-1];e[c]=[r,o,n]}}(),function(){s.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(t,{a:t}),t}}(),function(){s.d=function(e,t){for(var r in t)s.o(t,r)&&!s.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){s.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e}}(),function(){var e={524:0};s.O.j=function(t){return 0===e[t]};var t=function(t,r){var o,n,i=r[0],a=r[1],l=r[2],u=0;if(i.some((function(t){return 0!==e[t]}))){for(o in a)s.o(a,o)&&(s.m[o]=a[o]);if(l)var c=l(s)}for(t&&t(r);u<i.length;u++)n=i[u],s.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return s.O(c)},r=self["webpackChunkfrontend"]=self["webpackChunkfrontend"]||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))}();var r=s.O(void 0,[504],(function(){return s(6653)}));r=s.O(r)})();
//# sourceMappingURL=app.cd3a0313.js.map
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment