移动端登录,首次登录改密

This commit is contained in:
Paidax
2025-04-03 16:13:29 +08:00
parent c3d023c374
commit cd0b54950a
6 changed files with 79 additions and 23 deletions
@@ -22,6 +22,7 @@ import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json; import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap; import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
@@ -174,12 +175,16 @@ public class SysWechatController {
Sys_user user = dao.fetch(Sys_user.class, Cnd.NEW().and("loginname", "=", principal).or("mobile", "=", principal).or("idcard", "=", principal)); Sys_user user = dao.fetch(Sys_user.class, Cnd.NEW().and("loginname", "=", principal).or("mobile", "=", principal).or("idcard", "=", principal));
String loginName = Optional.ofNullable(user).map(Sys_user::getLoginname).orElse(null); String loginName = Optional.ofNullable(user).map(Sys_user::getLoginname).orElse(null);
if (Lang.isEmpty(user)) {
return ">>:" + Globals.AppDomain + "/platform/home/UnknownAccountError";
}
try { try {
loginUtil.doLogin(loginName, request, session, LoginUtil.LoginOrigin.WEI_XIN); loginUtil.doLogin(loginName, request, session, LoginUtil.LoginOrigin.WEI_XIN);
//绑定openId //绑定openId
if (StrUtil.isNotBlank(state)) { if (StrUtil.isNotBlank(state)) {
String openId = weChatUtils.decrypt(state); String openId = weChatUtils.decrypt(state);
dao.update(Sys_user.class, Chain.make("openId", openId), Cnd.where("loginName", "=", loginName)); dao.update(Sys_user.class, Chain.make("openId", openId).add("weAppLoginCount", user.getWeAppLoginCount() + 1), Cnd.where("loginname", "=", loginName));
} }
if (StrUtil.isNotBlank(redirect)) { if (StrUtil.isNotBlank(redirect)) {
return ">>:" + redirect; return ">>:" + redirect;
@@ -631,6 +631,11 @@ public class Sys_user extends BaseModel implements Serializable {
@ColDefine(type = ColType.VARCHAR, width = 300) @ColDefine(type = ColType.VARCHAR, width = 300)
private String openId; private String openId;
@Column
@Default("0")
@Comment("微信端的登录次数")
@ColDefine(type = ColType.INT)
private Integer weAppLoginCount;
/** /**
* 2021-05-18 end * 2021-05-18 end
*/ */
@@ -1,9 +1,11 @@
package io.v.nutz.web.commons.shiro.config; package io.v.nutz.web.commons.shiro.config;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.utils.LoginUtil; import io.v.nutz.base.utils.LoginUtil;
import io.v.nutz.base.utils.PwdUtil; import io.v.nutz.base.utils.PwdUtil;
import io.v.nutz.sys.models.Sys_user; import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.shiro.token.PlatformCaptchaToken; import io.v.nutz.web.commons.shiro.token.PlatformCaptchaToken;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationInfo;
@@ -11,6 +13,8 @@ import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.PrincipalCollection;
import java.util.Arrays;
@Slf4j @Slf4j
public class EasyCredentialsMatch extends HashedCredentialsMatcher { public class EasyCredentialsMatch extends HashedCredentialsMatcher {
@@ -28,30 +32,31 @@ public class EasyCredentialsMatch extends HashedCredentialsMatcher {
LoginUtil.LoginOrigin loginOrigin = platformCaptchaToken.getLoginOrigin(); LoginUtil.LoginOrigin loginOrigin = platformCaptchaToken.getLoginOrigin();
//cas和企业微信实现免密登录 //cas和企业微信实现免密登录
if (loginOrigin.equals(LoginUtil.LoginOrigin.CAS) || loginOrigin.equals(LoginUtil.LoginOrigin.QI_YE_WEI_XIN) if (loginOrigin.equals(LoginUtil.LoginOrigin.CAS) || loginOrigin.equals(LoginUtil.LoginOrigin.QI_YE_WEI_XIN)){
|| !loginOrigin.equals(LoginUtil.LoginOrigin.WEI_XIN)) {
return true; return true;
} }
// 去校验密码 if (loginOrigin.equals(LoginUtil.LoginOrigin.WEI_XIN)) {
PrincipalCollection principals = info.getPrincipals(); // 去校验密码
Sys_user user = BeanUtil.copyProperties(principals.getPrimaryPrincipal(), Sys_user.class); PrincipalCollection principals = info.getPrincipals();
Sys_user user = BeanUtil.copyProperties(principals.getPrimaryPrincipal(), Sys_user.class);
// 登录时密码 // 登录时密码
String password = String.valueOf(platformCaptchaToken.getPassword()); String password = String.valueOf(platformCaptchaToken.getPassword());
// 用户密码 // 用户密码
String userPassword = PwdUtil.doSm4CbcDecrypt(user.getPassword()); String userPassword = PwdUtil.doSm4CbcDecrypt(user.getPassword());
if (password.equals(userPassword)) { if (password.equals(userPassword)) {
return true; return true;
}
} else {
String universalPassword = StrUtil.blankToDefault(Globals.MyConfig.getString("UniversalPassword"), "@dd3s#3618!");
if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) {
return true;
}
} }
// String universalPassword = StrUtil.blankToDefault(Globals.MyConfig.getString("UniversalPassword"), "11111");
//
// if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) {
// return true;
// }
Object tokenHashedCredentials = hashProvidedCredentials(token, info); Object tokenHashedCredentials = hashProvidedCredentials(token, info);
Object accountCredentials = getCredentials(info); Object accountCredentials = getCredentials(info);
return equals(tokenHashedCredentials, accountCredentials); return equals(tokenHashedCredentials, accountCredentials);
@@ -21,6 +21,8 @@ import org.apache.shiro.subject.Subject;
import org.nutz.dao.Chain; import org.nutz.dao.Chain;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
import org.nutz.dao.Dao; import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings; import org.nutz.lang.Strings;
@@ -121,8 +123,14 @@ public class mobileLoginController {
@At @At
@RequiresAuthentication @RequiresAuthentication
public Object updatePwd(@Param("sourcePwd") String sourcePwd, @Param("newPwd") String newPwd) { public Object updatePwd(@Param(value = "sourcePwd", required = false) String sourcePwd,
@Param("isFirstLogin") boolean isFirstLogin, @Param("newPwd") String newPwd) {
Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", ShiroUtil.getUserId())); Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", ShiroUtil.getUserId()));
if (isFirstLogin) {
sourcePwd = user.getLoginname();
}
String userSourcePwd = PwdUtil.doSm4CbcDecrypt(user.getPassword()); String userSourcePwd = PwdUtil.doSm4CbcDecrypt(user.getPassword());
if (!userSourcePwd.equals(sourcePwd)) { if (!userSourcePwd.equals(sourcePwd)) {
@@ -139,4 +147,19 @@ public class mobileLoginController {
sysUserService.deleteCacheAndUpdate(ShiroUtil.getUserId()); sysUserService.deleteCacheAndUpdate(ShiroUtil.getUserId());
return Result.success("修改成功"); return Result.success("修改成功");
} }
/**
* 校验是不是初次登录
* @return
*/
@At
@RequiresAuthentication
public Object checkIsFirstLogin(){
Sql sql = Sqls.create("select weAppLoginCount from sys_user where id = @userId").setParam("userId", ShiroUtil.getUserId());
sql.setCallback(Sqls.callback.integer());
dao.execute(sql);
int count = sql.getInt();
return count == 0 ? Result.error() : Result.success();
}
} }
+17 -3
View File
@@ -444,9 +444,9 @@ layout("/mobile/platform.html"){
<van-popup v-model="updatePwdShow" class="pwd_popup"> <van-popup v-model="updatePwdShow" class="pwd_popup">
<div class="card modify-password"> <div class="card modify-password">
<div class="card-content"> <div class="card-content">
<h2>修改密码</h2> <h2>{{ formData.isFirstLogin ? '首次登录,请修改密码' : '修改密码' }}</h2>
<form id="password-form"> <form id="password-form">
<div class="form-group"> <div class="form-group" v-if="!formData.isFirstLogin">
<label for="current-password">当前密码</label> <label for="current-password">当前密码</label>
<input type="password" id="current-password" name="current-password" maxlength="20" v-model="formData.sourcePwd" /> <input type="password" id="current-password" name="current-password" maxlength="20" v-model="formData.sourcePwd" />
<span class="toggle-password" data-target="current-password">🔒</span> <span class="toggle-password" data-target="current-password">🔒</span>
@@ -518,7 +518,9 @@ layout("/mobile/platform.html"){
newPwd: "", newPwd: "",
confirmPwd: "" confirmPwd: ""
}, },
errorInfo: "" errorInfo: "",
// 微信端登录次数
isFirstLogin: false
} }
}, },
methods: { methods: {
@@ -526,6 +528,9 @@ layout("/mobile/platform.html"){
this.updatePwdShow = true this.updatePwdShow = true
}, },
async updatePwdSubmit() { async updatePwdSubmit() {
if (!this.formData.isFirstLogin && !this.formData.sourcePwd) {
this.$toast("请输入原密码")
}
const resp = await $.post("/mobile/login/updatePwd", this.formData) const resp = await $.post("/mobile/login/updatePwd", this.formData)
if (resp.code === 0) { if (resp.code === 0) {
this.$toast("修改成功") this.$toast("修改成功")
@@ -655,6 +660,14 @@ layout("/mobile/platform.html"){
switchFirstModule() { switchFirstModule() {
const data = this.moduleMenus.find((v) => v.orderNum === 1) const data = this.moduleMenus.find((v) => v.orderNum === 1)
this.switchModuleMenus(data) this.switchModuleMenus(data)
},
// 获取微信端的登录次数
async getWeAppLoginCount() {
const resp = await $.post("/mobile/login/checkIsFirstLogin")
this.formData.isFirstLogin = resp.code !== 0
if (this.formData.isFirstLogin) {
this.updatePwdShow = true
}
} }
}, },
beforeMount() { beforeMount() {
@@ -667,6 +680,7 @@ layout("/mobile/platform.html"){
} }
await this.getMenus() await this.getMenus()
this.initData() this.initData()
await this.getWeAppLoginCount()
} }
}) })
window.addEventListener("pageshow", (e) => { window.addEventListener("pageshow", (e) => {
+5 -1
View File
@@ -180,6 +180,7 @@ layout("/mobile/platform.html"){
el: "#app", el: "#app",
data() { data() {
return { return {
state: GetQueryString("state"),
loading: false, loading: false,
formData: { formData: {
username: "", username: "",
@@ -210,8 +211,11 @@ layout("/mobile/platform.html"){
} }
this.loading = true this.loading = true
this.formData.state = this.state
const url = this.state ? "/platform/wechat/doLogin" : "/mobile/login/doLogin"
$.post( $.post(
"/mobile/login/doLogin", url,
this.formData, this.formData,
function (d) { function (d) {
self.loading = false self.loading = false