diff --git a/JSD-8663-需求确认书V1.docx b/JSD-8663-需求确认书V1.docx
new file mode 100644
index 0000000..c1e3e2d
Binary files /dev/null and b/JSD-8663-需求确认书V1.docx differ
diff --git a/JSD-8663配置使用文档.docx b/JSD-8663配置使用文档.docx
new file mode 100644
index 0000000..3d2057e
Binary files /dev/null and b/JSD-8663配置使用文档.docx differ
diff --git a/README.md b/README.md
index 3da4aa6..517138d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,6 @@
# open-JSD-8663
-JSD-8663 开源任务材料
\ No newline at end of file
+JSD-8663 平台登出web接口 开源任务材料\
+免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
+仅作为开发者学习参考使用!禁止用于任何商业用途!\
+为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。
\ No newline at end of file
diff --git a/plugin.xml b/plugin.xml
new file mode 100644
index 0000000..30667aa
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,20 @@
+
+ com.fr.plugin.xxxx.logout
+
+ yes
+ 1.1
+ 10.0
+ 2018-07-31
+ holger
+
+
+ [2021-09-09]【1.1】允许跨域。
+ ]]>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestHandlerBridge.java b/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestHandlerBridge.java
new file mode 100644
index 0000000..73c8491
--- /dev/null
+++ b/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestHandlerBridge.java
@@ -0,0 +1,20 @@
+package com.fr.plugin.xxxx.logout;
+
+import com.fr.decision.fun.HttpHandler;
+import com.fr.decision.fun.impl.AbstractHttpHandlerProvider;
+import com.fr.plugin.xxxx.logout.handler.LogoutHandler;
+import com.fr.plugin.transform.FunctionRecorder;
+
+/**
+ * @Author fr.open
+ * @Date 2021/9/9
+ * @Description
+ **/
+@FunctionRecorder
+public class LogoutRequestHandlerBridge extends AbstractHttpHandlerProvider {
+ @Override
+ public HttpHandler[] registerHandlers() {
+ return new HttpHandler[]{new LogoutHandler()};
+ }
+
+}
diff --git a/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestURLAliasBridge.java b/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestURLAliasBridge.java
new file mode 100644
index 0000000..f818b62
--- /dev/null
+++ b/src/main/java/com/fr/plugin/xxxx/logout/LogoutRequestURLAliasBridge.java
@@ -0,0 +1,18 @@
+package com.fr.plugin.xxxx.logout;
+
+import com.fr.decision.fun.impl.AbstractURLAliasProvider;
+import com.fr.decision.webservice.url.alias.URLAlias;
+import com.fr.decision.webservice.url.alias.URLAliasFactory;
+
+/**
+ * @Author fr.open
+ * @Date 2021/9/9
+ * @Description
+ **/
+public class LogoutRequestURLAliasBridge extends AbstractURLAliasProvider {
+
+ @Override
+ public URLAlias[] registerAlias() {
+ return new URLAlias[]{URLAliasFactory.createPluginAlias("/quit", "/quit", true)};
+ }
+}
diff --git a/src/main/java/com/fr/plugin/xxxx/logout/handler/LogoutHandler.java b/src/main/java/com/fr/plugin/xxxx/logout/handler/LogoutHandler.java
new file mode 100644
index 0000000..24147b1
--- /dev/null
+++ b/src/main/java/com/fr/plugin/xxxx/logout/handler/LogoutHandler.java
@@ -0,0 +1,80 @@
+package com.fr.plugin.xxxx.logout.handler;
+
+import com.fr.decision.authority.data.User;
+import com.fr.decision.fun.impl.BaseHttpHandler;
+import com.fr.decision.webservice.exception.login.LoginInfoNotAvailableException;
+import com.fr.decision.webservice.v10.login.kickout.KickOutConfig;
+import com.fr.decision.webservice.v10.login.kickout.KickOutUserEvent;
+import com.fr.decision.webservice.v10.system.SystemService;
+import com.fr.decision.webservice.v10.user.UserService;
+import com.fr.event.EventDispatcher;
+import com.fr.intelligence.IntelligenceRuntimeException;
+import com.fr.json.JSONObject;
+import com.fr.log.FineLoggerFactory;
+import com.fr.stable.AssistUtils;
+import com.fr.third.springframework.web.bind.annotation.RequestMethod;
+import com.fr.web.utils.WebUtils;
+import com.fr.decision.webservice.Response;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @Author fr.open
+ * @Date 2021/9/9
+ * @Description
+ **/
+public class LogoutHandler extends BaseHttpHandler {
+ @Override
+ public RequestMethod getMethod() {
+ return RequestMethod.GET;
+ }
+
+ @Override
+ public String getPath() {
+ return "/quit";
+ }
+
+ @Override
+ public boolean isPublic() {
+ return true;
+ }
+
+ @Override
+ public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception {
+ res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
+ res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
+ res.setHeader("Access-Control-Max-Age", "0");
+ res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers");
+ res.setHeader("Access-Control-Allow-Credentials", "true");//这个是设置运行携带cookie
+ res.setHeader("XDomainRequestAllowed","1");
+ String username = WebUtils.getHTTPRequestParameter(req, "username");
+ Response response;
+ User user = UserService.getInstance().getUserByUserName(username);
+ if(user == null){
+ response = Response.error("user-not-exit","user-not-exit");
+ }else {
+ kickOutAllOtherCurrentUsers(username,new LoginInfoNotAvailableException());
+ response = Response.success();
+ }
+ WebUtils.printAsJSON(res, JSONObject.mapFrom(response));
+ }
+
+ private void kickOutAllOtherCurrentUsers(String currentUserName, IntelligenceRuntimeException runtimeException) {
+ try {
+ Set userNames = SystemService.getInstance().getSystemOnlineUserNames();
+ Iterator it = userNames.iterator();
+
+ while (it.hasNext()) {
+ String userName = (String) it.next();
+ if (AssistUtils.equals(userName, currentUserName)) {
+ EventDispatcher.fire(KickOutUserEvent.KickOutUser, new KickOutConfig(runtimeException, userName));
+ }
+ }
+ } catch (Exception var6) {
+ FineLoggerFactory.getLogger().error(var6.getMessage(), var6);
+ }
+
+ }
+}