feat: add support for Casdoor authentication (#39)
diff --git a/backend/pom.xml b/backend/pom.xml
index fb5d805..a7d67a9 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -145,6 +145,12 @@
</dependency>
<dependency>
+ <groupId>org.casbin</groupId>
+ <artifactId>casdoor-spring-boot-starter</artifactId>
+ <version>1.3.0</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-session</artifactId>
<version>0.12.5</version>
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java
index 93adb9a..9a001b1 100644
--- a/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java
@@ -33,6 +33,8 @@
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import org.casbin.casdoor.entity.CasdoorUser;
+import org.casbin.casdoor.service.CasdoorAuthService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -53,6 +55,8 @@
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
+ @Autowired private CasdoorAuthService casdoorAuthService;
+
@PostMapping("/login")
@ApiOperation("login")
public BaseVO<ConnectionVO> login(
@@ -71,6 +75,35 @@
return BaseVO.success("Login successful", connectionVO);
}
+ @PostMapping("/getCasdoorUrl")
+ @ApiOperation("Get Casdoor Url")
+ public BaseVO<String> getCasdoorUrl(HttpServletRequest request, HttpServletResponse response)
+ throws BaseException {
+ String origin = request.getParameter("origin");
+ String url = casdoorAuthService.getSigninUrl(origin);
+ return BaseVO.success("Get Url successful", url);
+ }
+
+ @PostMapping("/loginWithCasdoor")
+ @ApiOperation("loginWithCasdoor")
+ public BaseVO<ConnectionVO> loginWithCasdoor(
+ @RequestParam("code") String code,
+ @RequestParam("state") String state,
+ HttpServletResponse response)
+ throws BaseException {
+ String token = casdoorAuthService.getOAuthToken(code, state);
+ CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
+ User user = new User();
+ user.setId(casdoorUser.getRanking());
+ user.setName(casdoorUser.getName());
+ int userId = user.getId();
+ String name = user.getName();
+ List<ConnVO> connVOs = connectionService.getAllConnections(userId);
+ ConnectionVO connectionVO = new ConnectionVO(connVOs, userId, name);
+ response.addHeader("Authorization", JJwtTool.generateToken(user));
+ return BaseVO.success("Login successful", connectionVO);
+ }
+
@PostMapping("/save")
@ApiOperation("Create user (not used)")
public BaseVO save(@RequestBody User user) throws BaseException {
diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties
index e9e7335..e3fdf60 100644
--- a/backend/src/main/resources/application.properties
+++ b/backend/src/main/resources/application.properties
@@ -18,4 +18,11 @@
#
# Designate the configuration file
-spring.profiles.active=dev
\ No newline at end of file
+spring.profiles.active=dev
+
+casdoor.endpoint =
+casdoor.clientId =
+casdoor.clientSecret =
+casdoor.certificate =
+casdoor.organizationName =
+casdoor.applicationName =
\ No newline at end of file
diff --git a/frontend/.env b/frontend/.env
new file mode 100644
index 0000000..de09d64
--- /dev/null
+++ b/frontend/.env
@@ -0,0 +1 @@
+VUE_APP_CASDOOR=false
\ No newline at end of file
diff --git a/frontend/src/i18n/cn.js b/frontend/src/i18n/cn.js
index 03d2620..63ec22b 100644
--- a/frontend/src/i18n/cn.js
+++ b/frontend/src/i18n/cn.js
@@ -86,6 +86,7 @@
placeholderPassword: '请输入密码',
forgetPassWord: '忘记密码',
signIn: '登录',
+ signInWithCasdoor: 'Casdoor登录',
forgetPassword: '忘记密码',
forgetPasswordTip: '请联系系统管理员 WeChat:loveher147',
accountEmptyTip: '账号不能为空',
diff --git a/frontend/src/i18n/de.js b/frontend/src/i18n/de.js
index 6634c75..b988b5a 100644
--- a/frontend/src/i18n/de.js
+++ b/frontend/src/i18n/de.js
@@ -85,6 +85,7 @@
placeholderPassword: 'Passwort eingeben',
forgetPassWord: 'Passwort vergessen',
signIn: 'Anmelden',
+ signInWithCasdoor: 'Loggen Sie sich mit casdoor ein',
forgetPassword: 'Passwort vergessen',
forgetPasswordTip: 'Bitte kontaktieren Sie Ihren Administrator WeChat:loveher147',
accountEmptyTip: 'Benutzername darf nicht leer sein',
diff --git a/frontend/src/i18n/en.js b/frontend/src/i18n/en.js
index 87113a6..4008863 100644
--- a/frontend/src/i18n/en.js
+++ b/frontend/src/i18n/en.js
@@ -85,6 +85,7 @@
placeholderPassword: 'Please Input Password',
forgetPassWord: 'Forget Password',
signIn: 'Sign In',
+ signInWithCasdoor: 'Sign In With Casdoor',
forgetPassword: 'Forget Password',
forgetPasswordTip: 'Please Contact System Administrator WeChat:loveher147',
accountEmptyTip: 'Account Can Not Be Empty',
diff --git a/frontend/src/util/axios.js b/frontend/src/util/axios.js
index 193f878..e44c18f 100644
--- a/frontend/src/util/axios.js
+++ b/frontend/src/util/axios.js
@@ -22,7 +22,7 @@
import router from '../router';
const instance = axios.create({});
-const headerUrls = ['/api/login', '/api/downloadFile/template', '/api/downloadQueryLogFile'];
+const headerUrls = ['/api/login', '/api/loginWithCasdoor', '/api/downloadFile/template', '/api/downloadQueryLogFile'];
const exportUrl = '/exportData';
const downUrl = '/downloadFile';
instance.defaults.withCredentials = true;
diff --git a/frontend/src/views/Login/index.vue b/frontend/src/views/Login/index.vue
index 3b18b4f..3dd06f2 100644
--- a/frontend/src/views/Login/index.vue
+++ b/frontend/src/views/Login/index.vue
@@ -60,6 +60,9 @@
<el-button class="submit-btn" type="primary" @click="submitForm('ruleForm')">{{ $t('loginPage.signIn') }}</el-button>
</el-form-item>
</el-form>
+ <el-form-item v-if="casdoorSwitch === 'true'">
+ <el-button class="submit-btn" type="primary" @click="getLoginUrl()">{{ $t('loginPage.signInWithCasdoor') }}</el-button>
+ </el-form-item>
</div>
</div>
</div>
@@ -90,6 +93,7 @@
const formNameRef = ref(null);
const dialogVisible = ref(false);
const { t } = useI18n();
+ const casdoorSwitch = process.env.VUE_APP_CASDOOR;
const ruleForm = reactive({
account: '',
passport: '',
@@ -145,6 +149,7 @@
// if (store.state.isLogin) {
// router.push({ name: "Root" });
// }
+ LoginWithCasdoor();
});
const submitForm = () => {
@@ -164,6 +169,31 @@
});
};
+ const getLoginUrl = () => {
+ axios.post('/getCasdoorUrl', {}, { params: { origin: window.location.origin } }).then((res) => {
+ window.location.href = res.data;
+ });
+ };
+
+ const LoginWithCasdoor = () => {
+ const url = window.document.location.href;
+ const u = new URL(url);
+ let codes = u.searchParams.get('code');
+ let state = u.searchParams.get('state');
+ if (codes != null && state != null) {
+ axios.post('/loginWithCasdoor', {}, { params: { code: codes, state: state } }).then((res) => {
+ if (res?.data?.code === '0') {
+ localStorage.setItem('authorization', res?.headers?.authorization);
+ store.commit('setLogin', true);
+ store.commit('setUserInfo', res.data || {});
+ router.push({ name: 'Root' });
+ } else {
+ ElMessage.error(t(`loginPage.loginErrorTip`));
+ }
+ });
+ }
+ };
+
const showDialog = () => {
dialogVisible.value = true;
};
@@ -177,6 +207,9 @@
rules,
submitForm,
showDialog,
+ getLoginUrl,
+ LoginWithCasdoor,
+ casdoorSwitch,
};
},
components: { ElForm, ElFormItem, ElInput, ElButton, ElDialog, ElDropdown, ElDropdownMenu, ElDropdownItem },