mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 04:10:20 +08:00
fix: mask email and phone number on the backend (#563)
* fix: mask email and phone number on the backend Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com> * fix: login with masked email or phone Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com> * fix: improve regex Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>
This commit is contained in:
@ -167,9 +167,16 @@ func (c *ApiController) Login() {
|
|||||||
var verificationCodeType string
|
var verificationCodeType string
|
||||||
var checkResult string
|
var checkResult string
|
||||||
|
|
||||||
|
if form.Name != "" {
|
||||||
|
user = object.GetUserByFields(form.Organization, form.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// check result through Email or Phone
|
// check result through Email or Phone
|
||||||
if strings.Contains(form.Username, "@") {
|
if strings.Contains(form.Username, "@") {
|
||||||
verificationCodeType = "email"
|
verificationCodeType = "email"
|
||||||
|
if user != nil && util.GetMaskedEmail(user.Email) == form.Username {
|
||||||
|
form.Username = user.Email
|
||||||
|
}
|
||||||
checkResult = object.CheckVerificationCode(form.Username, form.Code)
|
checkResult = object.CheckVerificationCode(form.Username, form.Code)
|
||||||
} else {
|
} else {
|
||||||
verificationCodeType = "phone"
|
verificationCodeType = "phone"
|
||||||
@ -178,6 +185,9 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(responseText)
|
c.ResponseError(responseText)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if user != nil && util.GetMaskedPhone(user.Phone) == form.Username {
|
||||||
|
form.Username = user.Phone
|
||||||
|
}
|
||||||
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
||||||
checkResult = object.CheckVerificationCode(checkPhone, form.Code)
|
checkResult = object.CheckVerificationCode(checkPhone, form.Code)
|
||||||
}
|
}
|
||||||
|
@ -194,15 +194,19 @@ func (c *ApiController) GetEmailAndPhone() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
respUser := object.User{Email: user.Email, Phone: user.Phone, Name: user.Name}
|
respUser := object.User{Name: user.Name}
|
||||||
var contentType string
|
var contentType string
|
||||||
switch form.Username {
|
switch form.Username {
|
||||||
case user.Email:
|
case user.Email:
|
||||||
contentType = "email"
|
contentType = "email"
|
||||||
|
respUser.Email = user.Email
|
||||||
case user.Phone:
|
case user.Phone:
|
||||||
contentType = "phone"
|
contentType = "phone"
|
||||||
|
respUser.Phone = user.Phone
|
||||||
case user.Name:
|
case user.Name:
|
||||||
contentType = "username"
|
contentType = "username"
|
||||||
|
respUser.Email = util.GetMaskedEmail(user.Email)
|
||||||
|
respUser.Phone = util.GetMaskedPhone(user.Phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(respUser, contentType)
|
c.ResponseOk(respUser, contentType)
|
||||||
|
@ -74,8 +74,16 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendResp := errors.New("Invalid dest type")
|
sendResp := errors.New("Invalid dest type")
|
||||||
|
|
||||||
|
if user == nil && checkUser != "" && checkUser != "true" {
|
||||||
|
_, name := util.GetOwnerAndNameFromId(orgId)
|
||||||
|
user = object.GetUser(fmt.Sprintf("%s/%s", name, checkUser))
|
||||||
|
}
|
||||||
switch destType {
|
switch destType {
|
||||||
case "email":
|
case "email":
|
||||||
|
if user != nil && util.GetMaskedEmail(user.Email) == dest {
|
||||||
|
dest = user.Email
|
||||||
|
}
|
||||||
if !util.IsEmailValid(dest) {
|
if !util.IsEmailValid(dest) {
|
||||||
c.ResponseError("Invalid Email address")
|
c.ResponseError("Invalid Email address")
|
||||||
return
|
return
|
||||||
@ -84,6 +92,9 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
provider := application.GetEmailProvider()
|
provider := application.GetEmailProvider()
|
||||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, dest)
|
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, dest)
|
||||||
case "phone":
|
case "phone":
|
||||||
|
if user != nil && util.GetMaskedPhone(user.Phone) == dest {
|
||||||
|
dest = user.Phone
|
||||||
|
}
|
||||||
if !util.IsPhoneCnValid(dest) {
|
if !util.IsPhoneCnValid(dest) {
|
||||||
c.ResponseError("Invalid phone number")
|
c.ResponseError("Invalid phone number")
|
||||||
return
|
return
|
||||||
|
@ -20,10 +20,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var rePhoneCn *regexp.Regexp
|
var rePhoneCn *regexp.Regexp
|
||||||
|
var rePhone *regexp.Regexp
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// https://learnku.com/articles/31543
|
// https://learnku.com/articles/31543
|
||||||
rePhoneCn, _ = regexp.Compile(`^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$`)
|
rePhoneCn, _ = regexp.Compile(`^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$`)
|
||||||
|
rePhone, _ = regexp.Compile("(\\d{3})\\d*(\\d{4})")
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmailValid(email string) bool {
|
func IsEmailValid(email string) bool {
|
||||||
@ -34,3 +36,7 @@ func IsEmailValid(email string) bool {
|
|||||||
func IsPhoneCnValid(phone string) bool {
|
func IsPhoneCnValid(phone string) bool {
|
||||||
return rePhoneCn.MatchString(phone)
|
return rePhoneCn.MatchString(phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMaskedPhone(phone string) string {
|
||||||
|
return rePhone.ReplaceAllString(phone, "$1****$2")
|
||||||
|
}
|
@ -206,3 +206,28 @@ func IsChinese(str string) bool {
|
|||||||
}
|
}
|
||||||
return flag
|
return flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMaskedPhone(phone string) string {
|
||||||
|
return getMaskedPhone(phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaskedEmail(email string) string {
|
||||||
|
if email == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens := strings.Split(email, "@")
|
||||||
|
username := maskString(tokens[0])
|
||||||
|
domain := tokens[1]
|
||||||
|
domainTokens := strings.Split(domain, ".")
|
||||||
|
domainTokens[len(domainTokens) - 2] = maskString(domainTokens[len(domainTokens) - 2])
|
||||||
|
return fmt.Sprintf("%s@%s", username, strings.Join(domainTokens, "."))
|
||||||
|
}
|
||||||
|
|
||||||
|
func maskString(str string) string {
|
||||||
|
if len(str) <= 2 {
|
||||||
|
return str
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%c%s%c", str[0], strings.Repeat("*", len(str) - 2), str[len(str) - 1])
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Col, Form, Select, Input, Row, Steps} from "antd";
|
import {Button, Col, Form, Input, Row, Select, Steps} from "antd";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||||
import * as Util from "./Util";
|
import * as Util from "./Util";
|
||||||
@ -43,6 +43,7 @@ class ForgetPage extends React.Component {
|
|||||||
msg: null,
|
msg: null,
|
||||||
userId: "",
|
userId: "",
|
||||||
username: "",
|
username: "",
|
||||||
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
isFixed: false,
|
isFixed: false,
|
||||||
fixedContent: "",
|
fixedContent: "",
|
||||||
@ -100,7 +101,7 @@ class ForgetPage extends React.Component {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
const phone = res.data.phone;
|
const phone = res.data.phone;
|
||||||
const email = res.data.email;
|
const email = res.data.email;
|
||||||
this.setState({phone: phone, email: email, username: res.data.name});
|
this.setState({phone: phone, email: email, username: res.data.name, name: res.data.name});
|
||||||
|
|
||||||
if (phone !== "" && email === "") {
|
if (phone !== "" && email === "") {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -134,15 +135,16 @@ class ForgetPage extends React.Component {
|
|||||||
break;
|
break;
|
||||||
case "step2":
|
case "step2":
|
||||||
const oAuthParams = Util.getOAuthGetParameters();
|
const oAuthParams = Util.getOAuthGetParameters();
|
||||||
if(this.state.verifyType=="email"){
|
if (this.state.verifyType === "email") {
|
||||||
this.setState({username: this.state.email})
|
this.setState({username: this.state.email})
|
||||||
}else if(this.state.verifyType=="phone"){
|
} else if (this.state.verifyType === "phone") {
|
||||||
this.setState({username: this.state.phone})
|
this.setState({username: this.state.phone})
|
||||||
}
|
}
|
||||||
AuthBackend.login({
|
AuthBackend.login({
|
||||||
application: forms.step2.getFieldValue("application"),
|
application: forms.step2.getFieldValue("application"),
|
||||||
organization: forms.step2.getFieldValue("organization"),
|
organization: forms.step2.getFieldValue("organization"),
|
||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
|
name: this.state.name,
|
||||||
code: forms.step2.getFieldValue("emailCode"),
|
code: forms.step2.getFieldValue("emailCode"),
|
||||||
phonePrefix: this.state.application?.organizationObj.phonePrefix,
|
phonePrefix: this.state.application?.organizationObj.phonePrefix,
|
||||||
type: "login"
|
type: "login"
|
||||||
@ -179,7 +181,7 @@ class ForgetPage extends React.Component {
|
|||||||
if (this.state.phone !== "") {
|
if (this.state.phone !== "") {
|
||||||
options.push(
|
options.push(
|
||||||
<Option key={"phone"} value={"phone"}>
|
<Option key={"phone"} value={"phone"}>
|
||||||
{Setting.getMaskedPhone(this.state.phone)}
|
{this.state.phone}
|
||||||
</Option>
|
</Option>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -187,7 +189,7 @@ class ForgetPage extends React.Component {
|
|||||||
if (this.state.email !== "") {
|
if (this.state.email !== "") {
|
||||||
options.push(
|
options.push(
|
||||||
<Option key={"email"} value={"email"}>
|
<Option key={"email"} value={"email"}>
|
||||||
{Setting.getMaskedEmail(this.state.email)}
|
{this.state.email}
|
||||||
</Option>
|
</Option>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -349,12 +351,12 @@ class ForgetPage extends React.Component {
|
|||||||
{this.state.verifyType === "email" ? (
|
{this.state.verifyType === "email" ? (
|
||||||
<CountDownInput
|
<CountDownInput
|
||||||
disabled={this.state.username === "" || this.state.verifyType === ""}
|
disabled={this.state.username === "" || this.state.verifyType === ""}
|
||||||
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationOrgName(this.state.application)]}
|
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationOrgName(this.state.application), this.state.name]}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<CountDownInput
|
<CountDownInput
|
||||||
disabled={this.state.username === "" || this.state.verifyType === ""}
|
disabled={this.state.username === "" || this.state.verifyType === ""}
|
||||||
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationOrgName(this.state.application)]}
|
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationOrgName(this.state.application), this.state.name]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -49,14 +49,6 @@ export const CountDownInput = (props) => {
|
|||||||
|
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
if (isValidEmail(onButtonClickArgs[0])) {
|
|
||||||
onButtonClickArgs[1] = "email";
|
|
||||||
} else if (isValidPhone(onButtonClickArgs[0])) {
|
|
||||||
onButtonClickArgs[1] = "phone";
|
|
||||||
} else {
|
|
||||||
Util.showMessage("error", i18next.t("login:Invalid Email or phone"))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setButtonLoading(true)
|
setButtonLoading(true)
|
||||||
UserBackend.sendCode(checkType, checkId, key, ...onButtonClickArgs).then(res => {
|
UserBackend.sendCode(checkType, checkId, key, ...onButtonClickArgs).then(res => {
|
||||||
setKey("");
|
setKey("");
|
||||||
|
Reference in New Issue
Block a user