
--- client/resources/api/cntxtPth.js
+++ client/resources/api/cntxtPth.js
... | ... | @@ -1,21 +1,9 @@ |
1 | 1 |
import apiClient from "./index"; |
2 | 2 |
|
3 |
-export const findAll = search => { |
|
4 |
- return apiClient.post(`/admin/cntxtPth/findAll.json`, search); |
|
3 |
+export const getCntxtPth = () => { |
|
4 |
+ return apiClient.get(`/admin/cntxtPth/findLatestCntxtPth.json`); |
|
5 | 5 |
} |
6 | 6 |
|
7 |
-export const findByCntxtPth = cntxtPth => { |
|
8 |
- return apiClient.post(`/admin/cntxtPth/findByCntxtPth.json`, cntxtPth); |
|
9 |
-} |
|
10 |
- |
|
11 |
-export const save = cntxtPth => { |
|
7 |
+export const saveCntxtPth = cntxtPth => { |
|
12 | 8 |
return apiClient.post(`/admin/cntxtPth/saveProc.json`, cntxtPth); |
13 |
-} |
|
14 |
- |
|
15 |
-export const update = cntxtPth => { |
|
16 |
- return apiClient.post(`/admin/cntxtPth/updateProc.json`, cntxtPth); |
|
17 |
-} |
|
18 |
- |
|
19 |
-export const del = cntxtPth => { |
|
20 |
- return apiClient.post(`/admin/cntxtPth/deleteProc.json`, cntxtPth); |
|
21 | 9 |
}(파일 끝에 줄바꿈 문자 없음) |
--- client/resources/api/router.js
+++ client/resources/api/router.js
... | ... | @@ -1,9 +1,5 @@ |
1 | 1 |
import apiClient from "./index"; |
2 | 2 |
|
3 |
-export const getCntxtPth = () => { |
|
4 |
- return apiClient.get(`/admin/cntxtPth/findLatestCntxtPth.json`); |
|
5 |
-} |
|
6 |
- |
|
7 | 3 |
export const findAll = () => { |
8 | 4 |
return apiClient.post(`/sys/contsType/findByContsAuthrtSys.json`); |
9 | 5 |
} |
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
... | ... | @@ -21,7 +21,8 @@ |
21 | 21 |
}, |
22 | 22 |
]; |
23 | 23 |
|
24 |
-import { getCntxtPth, findAll, accessCheck } from "../../resources/api/router"; |
|
24 |
+import { findAll, accessCheck } from "../../resources/api/router"; |
|
25 |
+import { getCntxtPth } from "../../resources/api/cntxtPth"; |
|
25 | 26 |
import { save } from "../../resources/api/cntnStats"; |
26 | 27 |
import { mdiConsoleLine } from "@mdi/js"; |
27 | 28 |
|
--- client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
+++ client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
... | ... | @@ -3,127 +3,205 @@ |
3 | 3 |
<div class="content"> |
4 | 4 |
<div class="scroll"> |
5 | 5 |
<div open class="form-box"> |
6 |
- <div class="form-box-title"> |
|
7 |
- <p class="summary-style pl10">기본 정보</p> |
|
8 |
- <span style="color: red;"> ※ 로그인 정책을 변경하면 전체 사용자가 로그아웃됩니다.</span> |
|
9 |
- </div> |
|
10 |
- <div class="form-content"> |
|
11 |
- <div class="gd-12 pl0"> |
|
12 |
- <label class="form-title">중복로그인 설정</label> |
|
13 |
- <div class="form-group"> |
|
14 |
- <div class="check-area"> |
|
15 |
- <div class="form-check"> |
|
16 |
- <input type="radio" id="allowMultipleLoginY" class="mr5" value="Y" v-model="allowMultipleLogin" @change="saveByLoginPolicy" /> |
|
17 |
- <label for="allowMultipleLoginY">허용</label> |
|
18 |
- </div> |
|
19 |
- <div class="form-check"> |
|
20 |
- <input type="radio" id= "allowMultipleLoginN" class="mr5" value="N" v-model="allowMultipleLogin" @change="saveByLoginPolicy" /> |
|
21 |
- <label for="allowMultipleLoginN">비허용</label> |
|
22 |
- </div> |
|
23 |
- </div> |
|
24 |
- <!-- <p>{{ allowMultipleLogin ? '중복 로그인을 허용하고 있습니다.' : '중복 로그인을 허용하지 않습니다.' }}</p>--> |
|
6 |
+ <div class="form-box-title"> |
|
7 |
+ <p class="summary-style pl10">기본 정보</p> |
|
8 |
+ <span style="color: red;"> ※ 로그인 정책을 변경하면 전체 사용자가 로그아웃됩니다.</span> |
|
9 |
+ </div> |
|
10 |
+ <div class="form-content"> |
|
11 |
+ <div class="gd-12 pl0"> |
|
12 |
+ <label class="form-title">중복로그인 설정</label> |
|
13 |
+ <div class="form-group"> |
|
14 |
+ <div class="check-area"> |
|
15 |
+ <div class="form-check"> |
|
16 |
+ <input type="radio" id="allowMultipleLoginY" class="mr5" value="Y" v-model="allowMultipleLogin" |
|
17 |
+ @change="saveByLoginPolicy" /> |
|
18 |
+ <label for="allowMultipleLoginY">허용</label> |
|
25 | 19 |
</div> |
26 |
- </div> |
|
27 |
- <div> |
|
28 |
- <label class="form-title">로그인 방식 설정</label> |
|
29 |
- <div class="form-group"> |
|
30 |
- <div class="check-area"> |
|
31 |
- <div class="form-check"> |
|
32 |
- <input type="radio" id= "loginModeJ" class="mr5" value="J" v-model="lgnMode" @change="saveByLoginMode" /> |
|
33 |
- <label for="loginModeJ">JWT 방식</label> |
|
34 |
- </div> |
|
35 |
- <div class="form-check"> |
|
36 |
- <input type="radio" id= "loginModeS" class="mr5" value="S" v-model="lgnMode" @change="saveByLoginMode" /> |
|
37 |
- <label for="loginModeS">SESSION 방식</label> |
|
38 |
- </div> |
|
39 |
- </div> |
|
40 |
- <span class="ml10 gray"> |
|
41 |
- 현재 로그인 방식은 <strong>{{ loginModeLabel }}</strong> 입니다. |
|
42 |
- </span> |
|
43 |
- </div> |
|
20 |
+ <div class="form-check"> |
|
21 |
+ <input type="radio" id="allowMultipleLoginN" class="mr5" value="N" v-model="allowMultipleLogin" |
|
22 |
+ @change="saveByLoginPolicy" /> |
|
23 |
+ <label for="allowMultipleLoginN">비허용</label> |
|
24 |
+ </div> |
|
44 | 25 |
</div> |
26 |
+ <!-- <p>{{ allowMultipleLogin ? '중복 로그인을 허용하고 있습니다.' : '중복 로그인을 허용하지 않습니다.' }}</p>--> |
|
27 |
+ </div> |
|
45 | 28 |
</div> |
29 |
+ <div> |
|
30 |
+ <label class="form-title">로그인 방식 설정</label> |
|
31 |
+ <div class="form-group"> |
|
32 |
+ <div class="check-area"> |
|
33 |
+ <div class="form-check"> |
|
34 |
+ <input type="radio" id="loginModeJ" class="mr5" value="J" v-model="lgnMode" |
|
35 |
+ @change="saveByLoginMode" /> |
|
36 |
+ <label for="loginModeJ">JWT 방식</label> |
|
37 |
+ </div> |
|
38 |
+ <div class="form-check"> |
|
39 |
+ <input type="radio" id="loginModeS" class="mr5" value="S" v-model="lgnMode" |
|
40 |
+ @change="saveByLoginMode" /> |
|
41 |
+ <label for="loginModeS">SESSION 방식</label> |
|
42 |
+ </div> |
|
43 |
+ </div> |
|
44 |
+ <span class="ml10 gray"> |
|
45 |
+ 현재 로그인 방식은 <strong>{{ loginModeLabel }}</strong> 입니다. |
|
46 |
+ </span> |
|
47 |
+ </div> |
|
48 |
+ </div> |
|
49 |
+ <div> |
|
50 |
+ <label class="form-title">Context Path 설정</label> |
|
51 |
+ <div class="form-group"> |
|
52 |
+ <div class="check-area"> |
|
53 |
+ <div class="form-check"> |
|
54 |
+ <input type="text" id="cntxtPth" class="form-control sm" v-model="cntxtPth" ref="cntxtPth" /> |
|
55 |
+ </div> |
|
56 |
+ <button class="btn sm primary" @click="fnSave">저장</button> |
|
57 |
+ </div> |
|
58 |
+ <span class="ml10 gray"> |
|
59 |
+ <strong>/경로</strong> 형식으로 입력해주세요. |
|
60 |
+ </span> |
|
61 |
+ </div> |
|
62 |
+ </div> |
|
63 |
+ </div> |
|
46 | 64 |
</div> |
47 | 65 |
</div> |
48 | 66 |
</div> |
49 | 67 |
</div> |
50 | 68 |
</template> |
51 |
- |
|
52 |
- <script> |
|
53 |
- import { findAllByLoginPolicy, saveByLoginPolicy, findAllByLoginMode, saveByLoginMode } from '../../../../../resources/api/loginPolicy' |
|
54 |
- import store from "../../../../../views/pages/AppStore"; |
|
55 |
- export default { |
|
56 |
- data() { |
|
57 |
- return { |
|
58 |
- allowMultipleLogin: null, |
|
59 |
- lgnMode : null, |
|
60 |
- previousLgnMode: null, // 이전 로그인 모드 저장 |
|
61 |
- previousAllowMultipleLogin: null |
|
62 |
- } |
|
63 |
- }, |
|
64 |
- created() { |
|
65 |
- this.findAll(); |
|
66 |
- }, |
|
67 |
- mounted() { |
|
68 |
- }, |
|
69 |
- computed: { |
|
70 |
- loginModeLabel() { |
|
71 |
- return this.lgnMode === 'J' ? 'JWT' : 'SESSION'; |
|
72 |
- } |
|
73 |
- }, |
|
74 |
- methods: { |
|
75 |
- async findAll() { |
|
76 |
- try { |
|
77 |
- const res1 = await findAllByLoginPolicy(); |
|
78 |
- this.allowMultipleLogin = res1.data.data === true ? 'Y' : 'N'; |
|
79 |
- this.previousAllowMultipleLogin = this.allowMultipleLogin; |
|
80 |
- const res2 = await findAllByLoginMode(); |
|
81 |
- this.lgnMode = res2.data.data; |
|
82 |
- this.previousLgnMode = this.lgnMode; // 초기 상태를 저장 |
|
83 |
- } catch (err) { |
|
84 |
- alert('설정 정보를 불러오는 데 실패했습니다.'); |
|
85 |
- } |
|
86 |
- }, |
|
87 |
- async saveByLoginPolicy() { |
|
88 |
- const confirmed = confirm( |
|
89 |
- '로그인 설정을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?' |
|
90 |
- ); |
|
91 |
- if (!confirmed) { |
|
92 |
- this.allowMultipleLogin = this.previousAllowMultipleLogin; |
|
93 |
- return; |
|
94 |
- } |
|
95 | 69 |
|
96 |
- try { |
|
97 |
- const loginPolicy = {}; |
|
98 |
- loginPolicy.allowMultipleLogin = this.allowMultipleLogin; |
|
99 |
- await saveByLoginPolicy(loginPolicy); |
|
100 |
- alert('중복 로그인 설정이 저장되었습니다.'); |
|
101 |
- } catch (err) { |
|
102 |
- alert('중복 로그인 설정 저장 실패'); |
|
103 |
- this.allowMultipleLogin = this.previousAllowMultipleLogin; |
|
104 |
- } |
|
105 |
- }, |
|
106 |
- async saveByLoginMode() { |
|
107 |
- const confirmed = confirm( |
|
108 |
- '로그인 방식을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?' |
|
109 |
- ); |
|
110 |
- if (!confirmed) { |
|
111 |
- this.lgnMode = this.previousLgnMode; |
|
112 |
- return; |
|
113 |
- } |
|
70 |
+<script> |
|
71 |
+import { findAllByLoginPolicy, saveByLoginPolicy, findAllByLoginMode, saveByLoginMode } from '../../../../../resources/api/loginPolicy'; |
|
72 |
+import { getCntxtPth, saveCntxtPth } from '../../../../../resources/api/cntxtPth'; |
|
73 |
+import { cacheReSet } from "../../../../../resources/api/cacheReSet"; |
|
74 |
+import store from "../../../../../views/pages/AppStore"; |
|
75 |
+export default { |
|
76 |
+ data() { |
|
77 |
+ return { |
|
78 |
+ allowMultipleLogin: null, |
|
79 |
+ lgnMode: null, |
|
80 |
+ previousLgnMode: null, // 이전 로그인 모드 저장 |
|
81 |
+ previousAllowMultipleLogin: null, |
|
114 | 82 |
|
115 |
- try { |
|
116 |
- const loginMode = {}; |
|
117 |
- loginMode.lgnMode = this.lgnMode; |
|
118 |
- // await saveByLoginMode(loginMode); |
|
119 |
- alert('로그인 방식이 변경되었습니다.\n다시 로그인해주세요.'); |
|
120 |
- store.commit("setStoreReset"); |
|
121 |
- window.location = '/login.page'; |
|
122 |
- } catch (err) { |
|
123 |
- alert('로그인 방식 저장 실패: ' + (err.response?.data?.message || err.message)); |
|
124 |
- this.lgnMode = this.previousLgnMode; |
|
125 |
- } |
|
126 |
- } |
|
83 |
+ cntxtPth: '/', // context path 초기값 |
|
84 |
+ defaultCntxtPth: null, // 현재 설정된 Context Path |
|
127 | 85 |
} |
86 |
+ }, |
|
87 |
+ created() { |
|
88 |
+ this.findAll(); |
|
89 |
+ this.findCntxtPth(); |
|
90 |
+ }, |
|
91 |
+ mounted() { |
|
92 |
+ }, |
|
93 |
+ computed: { |
|
94 |
+ loginModeLabel() { |
|
95 |
+ return this.lgnMode === 'J' ? 'JWT' : 'SESSION'; |
|
96 |
+ } |
|
97 |
+ }, |
|
98 |
+ methods: { |
|
99 |
+ async findAll() { |
|
100 |
+ try { |
|
101 |
+ const res1 = await findAllByLoginPolicy(); |
|
102 |
+ this.allowMultipleLogin = res1.data.data === true ? 'Y' : 'N'; |
|
103 |
+ this.previousAllowMultipleLogin = this.allowMultipleLogin; |
|
104 |
+ const res2 = await findAllByLoginMode(); |
|
105 |
+ this.lgnMode = res2.data.data; |
|
106 |
+ this.previousLgnMode = this.lgnMode; // 초기 상태를 저장 |
|
107 |
+ } catch (err) { |
|
108 |
+ alert('설정 정보를 불러오는 데 실패했습니다.'); |
|
109 |
+ } |
|
110 |
+ }, |
|
111 |
+ async saveByLoginPolicy() { |
|
112 |
+ const confirmed = confirm( |
|
113 |
+ '로그인 설정을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?' |
|
114 |
+ ); |
|
115 |
+ if (!confirmed) { |
|
116 |
+ this.allowMultipleLogin = this.previousAllowMultipleLogin; |
|
117 |
+ return; |
|
118 |
+ } |
|
119 |
+ |
|
120 |
+ try { |
|
121 |
+ const loginPolicy = {}; |
|
122 |
+ loginPolicy.allowMultipleLogin = this.allowMultipleLogin; |
|
123 |
+ await saveByLoginPolicy(loginPolicy); |
|
124 |
+ alert('중복 로그인 설정이 저장되었습니다.'); |
|
125 |
+ } catch (err) { |
|
126 |
+ alert('중복 로그인 설정 저장 실패'); |
|
127 |
+ this.allowMultipleLogin = this.previousAllowMultipleLogin; |
|
128 |
+ } |
|
129 |
+ }, |
|
130 |
+ async saveByLoginMode() { |
|
131 |
+ const confirmed = confirm( |
|
132 |
+ '로그인 방식을 변경하면 전체 사용자가 로그아웃됩니다.\n계속하시겠습니까?' |
|
133 |
+ ); |
|
134 |
+ if (!confirmed) { |
|
135 |
+ this.lgnMode = this.previousLgnMode; |
|
136 |
+ return; |
|
137 |
+ } |
|
138 |
+ |
|
139 |
+ try { |
|
140 |
+ const loginMode = {}; |
|
141 |
+ loginMode.lgnMode = this.lgnMode; |
|
142 |
+ // await saveByLoginMode(loginMode); |
|
143 |
+ alert('로그인 방식이 변경되었습니다.\n다시 로그인해주세요.'); |
|
144 |
+ store.commit("setStoreReset"); |
|
145 |
+ window.location = '/login.page'; |
|
146 |
+ } catch (err) { |
|
147 |
+ alert('로그인 방식 저장 실패: ' + (err.response?.data?.message || err.message)); |
|
148 |
+ this.lgnMode = this.previousLgnMode; |
|
149 |
+ } |
|
150 |
+ }, |
|
151 |
+ |
|
152 |
+ // 최신 Context Path 조회 |
|
153 |
+ async findCntxtPth() { |
|
154 |
+ try { |
|
155 |
+ const res = await getCntxtPth(); |
|
156 |
+ if (res.status == 200) { |
|
157 |
+ this.cntxtPth = res.data.data; |
|
158 |
+ this.defaultCntxtPth = res.data.data; |
|
159 |
+ } |
|
160 |
+ } catch (error) { |
|
161 |
+ alert(error.response.data.message); |
|
162 |
+ } |
|
163 |
+ }, |
|
164 |
+ |
|
165 |
+ // Context Path 저장 |
|
166 |
+ async fnSave() { |
|
167 |
+ if (!this.validation()) { |
|
168 |
+ return; |
|
169 |
+ } |
|
170 |
+ const isCheck = confirm("Context Path를 변경하면 로그아웃됩니다.\n계속하시겠습니까?"); |
|
171 |
+ if (isCheck) { |
|
172 |
+ try { |
|
173 |
+ let ctx = {path: this.cntxtPth}; |
|
174 |
+ const res = await saveCntxtPth(ctx); |
|
175 |
+ alert(res.data.message); |
|
176 |
+ if (res.status == 200) { |
|
177 |
+ store.commit("setStoreReset"); |
|
178 |
+ const cacheRes = await cacheReSet(); // 캐시 초기화 |
|
179 |
+ alert(cacheRes.data.message); |
|
180 |
+ window.location = `${store.state.contextPath}/login.page`; |
|
181 |
+ } else { |
|
182 |
+ alert(res.data.message); |
|
183 |
+ } |
|
184 |
+ } catch (error) { |
|
185 |
+ alert('에러가 발생했습니다.\n시스템관리자에게 문의하세요.'); |
|
186 |
+ } |
|
187 |
+ } |
|
188 |
+ }, |
|
189 |
+ |
|
190 |
+ // 유효성 검사 |
|
191 |
+ validation() { |
|
192 |
+ const regex = /^\/[a-zA-Z0-9\-_]*$/; |
|
193 |
+ if (this.cntxtPth == null || this.cntxtPth == "") { |
|
194 |
+ alert("Context Path를 입력해주세요."); |
|
195 |
+ this.$refs.cntxtPth.focus(); |
|
196 |
+ return false; |
|
197 |
+ } |
|
198 |
+ if(!regex.test(this.cntxtPth)) { |
|
199 |
+ alert("Context Path는 '/'로 시작해야 하며, 알파벳, 숫자, '-' 또는 '_'만 포함할 수 있습니다."); |
|
200 |
+ this.$refs.cntxtPth.focus(); |
|
201 |
+ return false; |
|
202 |
+ } |
|
203 |
+ return true; |
|
204 |
+ }, |
|
128 | 205 |
} |
129 |
- </script>(파일 끝에 줄바꿈 문자 없음) |
|
206 |
+} |
|
207 |
+</script>(파일 끝에 줄바꿈 문자 없음) |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?