提交 43ae3dd2 编写于 作者: C Captain.B

feat(xPack): CAS 登录

上级 26edcd1e
......@@ -312,24 +312,6 @@
<scope>runtime</scope>
</dependency>
<!-- buji-pac4j -->
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-cas</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>io.buji</groupId>
<artifactId>buji-pac4j</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<artifactId>shiro-web</artifactId>
<groupId>org.apache.shiro</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
......
......@@ -21,7 +21,12 @@ public class ShiroUtils {
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/display/info", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/display/file/**", "anon");
filterChainDefinitionMap.put("/jmeter/download/**", "anon");
filterChainDefinitionMap.put("/authsource/list/allenable", "anon");
filterChainDefinitionMap.put("/sso/signin", "anon");
// for swagger
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-ui/**", "anon");
......
package io.metersphere.config;
import io.metersphere.commons.user.UserModularRealmAuthenticator;
import io.metersphere.commons.utils.ShiroUtils;
import io.metersphere.security.ApiKeyFilter;
import io.metersphere.security.LdapRealm;
import io.metersphere.security.ShiroDBRealm;
import io.metersphere.security.UserModularRealmAuthenticator;
import io.metersphere.security.realm.LdapRealm;
import io.metersphere.security.realm.ShiroDBRealm;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
......@@ -46,10 +46,7 @@ public class ShiroConfig implements EnvironmentAware {
shiroFilterFactoryBean.getFilters().put("apikey", new ApiKeyFilter());
Map<String, String> filterChainDefinitionMap = shiroFilterFactoryBean.getFilterChainDefinitionMap();
ShiroUtils.loadBaseFilterChain(filterChainDefinitionMap);
filterChainDefinitionMap.put("/display/info", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/display/file/**", "anon");
filterChainDefinitionMap.put("/jmeter/download/**", "anon");
filterChainDefinitionMap.put("/**", "apikey, authc");
return shiroFilterFactoryBean;
}
......
package io.metersphere.controller;
import io.metersphere.commons.utils.SessionUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -23,15 +22,4 @@ public class IndexController {
return "redirect:/";
}
}
@GetMapping(value = "/sso/login")
public String ossLogin() {
return "redirect:/";
}
@GetMapping(value = "/sso/logout")
public void ossLogout() {
SecurityUtils.getSubject().logout();
}
}
......@@ -8,4 +8,5 @@ import lombok.Setter;
public class LoginRequest {
private String username;
private String password;
private String authenticate;
}
package io.metersphere.security;
import io.metersphere.commons.user.MsUserToken;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
......
package io.metersphere.commons.user;
package io.metersphere.security;
import org.apache.shiro.authc.UsernamePasswordToken;
......
package io.metersphere.commons.user;
package io.metersphere.security;
import io.metersphere.commons.exception.MSException;
import org.apache.shiro.authc.AuthenticationException;
......
package io.metersphere.security;
package io.metersphere.security.realm;
import io.metersphere.base.domain.Role;
......
package io.metersphere.security;
package io.metersphere.security.realm;
import io.metersphere.base.domain.Role;
......
......@@ -8,7 +8,6 @@ import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.constants.UserSource;
import io.metersphere.commons.constants.UserStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.MsUserToken;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.CodingUtil;
import io.metersphere.commons.utils.SessionUtils;
......@@ -24,6 +23,7 @@ import io.metersphere.dto.UserDTO;
import io.metersphere.dto.UserRoleDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.notice.domain.UserDetail;
import io.metersphere.security.MsUserToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
......@@ -559,16 +559,14 @@ public class UserService {
String login = (String) SecurityUtils.getSubject().getSession().getAttribute("authenticate");
String username = StringUtils.trim(request.getUsername());
String password = "";
String loginType = UserSource.LDAP.name();
if (!StringUtils.equals(login, UserSource.LDAP.name())) {
loginType = UserSource.LOCAL.name();
password = StringUtils.trim(request.getPassword());
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
return ResultHolder.error("user or password can't be null");
}
}
MsUserToken token = new MsUserToken(username, password, loginType);
MsUserToken token = new MsUserToken(username, password, login);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
......
Subproject commit 36116c1bff736377e6b8a3b828c5fa9bd8b2f2f8
Subproject commit c2ed883e9be6fc7e01589f81916bf4ddc62148c0
<template>
<el-dropdown size="medium" @command="handleCommand" class="align-right">
<span class="dropdown-link">
{{currentUser.name}}<i class="el-icon-caret-bottom el-icon--right"/>
{{ currentUser.name }}<i class="el-icon-caret-bottom el-icon--right"/>
</span>
<template v-slot:dropdown>
<el-dropdown-menu>
......@@ -23,82 +23,77 @@
</template>
<script>
import {getCurrentUser} from "../../../../common/js/utils";
import AboutUs from "./AboutUs";
import axios from "axios";
import {getCurrentUser} from "@/common/js/utils";
import AboutUs from "./AboutUs";
import axios from "axios";
export default {
name: "MsUser",
components: {AboutUs},
data() {
return {
isReadOnly: this.$store.state.isReadOnly.flag
export default {
name: "MsUser",
components: {AboutUs},
data() {
return {
isReadOnly: this.$store.state.isReadOnly.flag
}
},
computed: {
currentUser: () => {
return getCurrentUser();
}
},
methods: {
handleCommand(command) {
switch (command) {
case "personal":
// TODO 优化路由跳转,避免重复添加路由
this.$router.push('/setting/personsetting').catch(error => error);
break;
case "logout":
axios.get("/signout").then(response => {
if (response.data.success) {
localStorage.clear();
window.location.href = "/login";
}
}).catch(error => {
localStorage.clear();
window.location.href = "/login";
});
break;
case "about":
this.$refs.aboutUs.open();
break;
case "help":
window.location.href = "https://metersphere.io/docs/index.html";
break;
default:
break;
}
},
computed: {
currentUser: () => {
return getCurrentUser();
changeBar(item) {
this.isReadOnly = !this.isReadOnly
this.$store.commit('setFlag', this.isReadOnly);
this.$store.commit('setValue', item);
if (item == "old") {
window.location.href = "/#/api/home_obsolete";
} else {
window.location.href = "/#/api/home";
}
},
methods: {
handleCommand(command) {
switch (command) {
case "personal":
// TODO 优化路由跳转,避免重复添加路由
this.$router.push('/setting/personsetting').catch(error => error);
break;
case "logout":
axios.get("/signout").then(response => {
if (response.data.success) {
localStorage.clear();
window.location.href = "/login";
} else {
if (response.data.message === 'sso') {
localStorage.clear();
window.location.href = "/sso/logout"
}
}
}).catch(error => {
localStorage.clear();
window.location.href = "/login";
});
break;
case "about":
this.$refs.aboutUs.open();
break;
case "help":
window.location.href = "https://metersphere.io/docs/index.html";
break;
default:
break;
}
},
changeBar(item) {
this.isReadOnly = !this.isReadOnly
this.$store.commit('setFlag', this.isReadOnly);
this.$store.commit('setValue', item);
if(item=="old"){
window.location.href = "/#/api/home_obsolete";
}else {
window.location.href = "/#/api/home";
}
}
}
}
}
</script>
<style scoped>
.dropdown-link {
cursor: pointer;
font-size: 12px;
color: rgb(245, 245, 245);
line-height: 40px;
}
.dropdown-link {
cursor: pointer;
font-size: 12px;
color: rgb(245, 245, 245);
line-height: 40px;
}
.align-right {
float: right;
}
.align-right {
float: right;
}
</style>
......
Subproject commit 3d96d7c61bc50f32f18311d23f447663e02d7d44
Subproject commit cea763d974b213104f6d6fc30ab48434b72e10f4
......@@ -18,6 +18,7 @@
<el-radio-group v-model="form.authenticate">
<el-radio label="LDAP" size="mini" v-if="openLdap">LDAP</el-radio>
<el-radio label="LOCAL" size="mini" v-if="openLdap">普通登录</el-radio>
<el-radio :label="auth.id" size="mini" v-for="auth in authSources" :key="auth.id">{{ auth.type }} {{ auth.name }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="username">
......@@ -52,6 +53,7 @@ import {DEFAULT_LANGUAGE} from "@/common/js/constants";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const display = requireComponent.keys().length > 0 ? requireComponent("./display/Display.vue") : {};
const auth = requireComponent.keys().length > 0 ? requireComponent("./auth/Auth.vue") : {};
export default {
name: "Login",
......@@ -84,7 +86,9 @@ export default {
msg: '',
ready: false,
openLdap: false,
loginTitle: this.$t("commons.login") + " MeterSphere"
loginTitle: this.$t("commons.login") + " MeterSphere",
authSources: [],
loginUrl: 'signin',
}
},
beforeCreate() {
......@@ -94,17 +98,17 @@ export default {
display.default.showLogin(this);
}
if (auth.default !== undefined) {
auth.default.getAuthSources(this);
}
if (!response.data.success) {
if (response.data.message === 'sso') {
window.location.href = "/sso/login"
} else {
this.ready = true;
}
this.ready = true;
} else {
let user = response.data.data;
saveLocalStorage(response.data);
this.getLanguage(user.language);
window.location.href = "/"
window.location.href = "/";
}
});
this.$get("/ldap/open", response => {
......@@ -135,28 +139,24 @@ export default {
if (valid) {
switch (this.form.authenticate) {
case "LOCAL":
this.normalLogin();
this.loginUrl = "/signin";
this.doLogin();
break;
case "LDAP":
this.ldapLogin();
this.loginUrl = "/ldap/signin";
this.doLogin();
break;
default:
this.normalLogin();
this.loginUrl = "/sso/signin";
this.doLogin();
}
} else {
return false;
}
});
},
normalLogin() {
this.result = this.$post("signin", this.form, response => {
saveLocalStorage(response);
sessionStorage.setItem('loginSuccess', 'true');
this.getLanguage(response.data.language);
});
},
ldapLogin() {
this.result = this.$post("ldap/signin", this.form, response => {
doLogin() {
this.result = this.$post(this.loginUrl, this.form, response => {
saveLocalStorage(response);
sessionStorage.setItem('loginSuccess', 'true');
this.getLanguage(response.data.language);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册