pull/1121/head
parent
56f8abbc12
commit
d641eb102a
|
|
@ -135,6 +135,8 @@ public class StoreUserController extends BaseController {
|
|||
Assert.notNull(storeId);
|
||||
Assert.notEmpty(vo.getPhonenumber(), "用户手机号不能为空");
|
||||
Set<Long> subRoleIds = roleService.getSubRoleIdsByStore(storeId);
|
||||
CollUtil.emptyIfNull(vo.getRoleIds())
|
||||
.forEach(roleId -> Assert.isTrue(subRoleIds.contains(roleId), "角色非法"));
|
||||
UserInfo info = userService.getUserByPhoneNumber(vo.getPhonenumber());
|
||||
Assert.notNull(info, "用户不存在");
|
||||
List<Long> roleIds = new ArrayList<>();
|
||||
|
|
@ -153,8 +155,8 @@ public class StoreUserController extends BaseController {
|
|||
}
|
||||
UserInfoEdit dto = BeanUtil.toBean(info, UserInfoEdit.class);
|
||||
roleIds.addAll(CollUtil.emptyIfNull(vo.getRoleIds()));
|
||||
dto.setUserName(vo.getUserName());
|
||||
dto.setRoleIds(roleIds);
|
||||
dto.setUserName(vo.getUserName());
|
||||
Long userId = userService.updateUser(dto);
|
||||
// 清除用户缓存(退出登录)
|
||||
tokenService.deleteCacheUser(userId);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.ruoyi.system.service.ISysMenuService;
|
|||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import com.ruoyi.web.controller.system.vo.*;
|
||||
import com.ruoyi.xkt.manager.AliAuthManager;
|
||||
import com.ruoyi.xkt.service.IStoreService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
|
@ -59,6 +60,8 @@ public class SysLoginController {
|
|||
private TokenService tokenService;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@Autowired
|
||||
private AliAuthManager aliAuthManager;
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
|
|
@ -69,14 +72,17 @@ public class SysLoginController {
|
|||
@ApiOperation(value = "用户名密码登录")
|
||||
@PostMapping("/loginByUname")
|
||||
public AjaxResult login(@Validated @RequestBody LoginByUsernameVO loginBody) {
|
||||
boolean captchaPass = aliAuthManager.validate(loginBody.getLot_number(), loginBody.getCaptcha_output(),
|
||||
loginBody.getPass_token(), loginBody.getGen_time());
|
||||
if (!captchaPass) {
|
||||
return AjaxResult.error("验证失败");
|
||||
}
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
// 生成令牌
|
||||
LoginCredential credential = LoginCredential.builder()
|
||||
.loginType(ELoginType.USERNAME)
|
||||
.username(loginBody.getUsername())
|
||||
.password(loginBody.getPassword())
|
||||
.imgUuid(loginBody.getUuid())
|
||||
.imgVerificationCode(loginBody.getCode())
|
||||
.build();
|
||||
String token = loginService.login(credential);
|
||||
ajax.put(Constants.TOKEN, token);
|
||||
|
|
@ -101,7 +107,12 @@ public class SysLoginController {
|
|||
@ApiOperation(value = "发送登录短信验证码")
|
||||
@PostMapping("/sendSmsVerificationCode")
|
||||
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
|
||||
loginService.sendSmsVerificationCode(vo.getPhoneNumber(), true, vo.getCode(), vo.getUuid());
|
||||
boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(),
|
||||
vo.getPass_token(), vo.getGen_time());
|
||||
if (!captchaPass) {
|
||||
return R.fail("验证失败");
|
||||
}
|
||||
loginService.sendSmsVerificationCode(vo.getPhoneNumber(), false, null, null);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.ruoyi.system.service.ISysUserService;
|
|||
import com.ruoyi.web.controller.system.vo.LoginSmsReqVO;
|
||||
import com.ruoyi.web.controller.system.vo.RegisterBySmsCodeVO;
|
||||
import com.ruoyi.web.controller.xkt.vo.PhoneNumberVO;
|
||||
import com.ruoyi.xkt.manager.AliAuthManager;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -45,6 +46,9 @@ public class SysRegisterController extends BaseController {
|
|||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private AliAuthManager aliAuthManager;
|
||||
|
||||
@ApiOperation(value = "档口供应商注册")
|
||||
@PostMapping("/registerStore")
|
||||
public AjaxResult registerStore(@Validated @RequestBody RegisterBySmsCodeVO vo) {
|
||||
|
|
@ -90,7 +94,12 @@ public class SysRegisterController extends BaseController {
|
|||
@ApiOperation(value = "发送登录短信验证码")
|
||||
@PostMapping("/sendSmsVerificationCode")
|
||||
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
|
||||
loginService.sendSmsVerificationCode(vo.getPhoneNumber(), true, vo.getCode(), vo.getUuid());
|
||||
boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(),
|
||||
vo.getPass_token(), vo.getGen_time());
|
||||
if (!captchaPass) {
|
||||
return R.fail("验证失败");
|
||||
}
|
||||
loginService.sendSmsVerificationCode(vo.getPhoneNumber(), false, null, null);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package com.ruoyi.web.controller.system.vo;
|
||||
|
||||
import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
|
|
@ -12,7 +15,9 @@ import javax.validation.constraints.NotEmpty;
|
|||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class LoginByUsernameVO {
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class LoginByUsernameVO extends AliCaptchaAuthReqVO {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
|
|
@ -26,16 +31,4 @@ public class LoginByUsernameVO {
|
|||
@NotEmpty(message = "用户密码不能为空")
|
||||
@ApiModelProperty(value = "用户密码", required = true)
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@ApiModelProperty("图形验证码")
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 唯一标识
|
||||
*/
|
||||
@ApiModelProperty("图形验证码唯一标识")
|
||||
private String uuid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package com.ruoyi.web.controller.system.vo;
|
||||
|
||||
import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
|
@ -13,16 +16,12 @@ import javax.validation.constraints.Pattern;
|
|||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class LoginSmsReqVO {
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class LoginSmsReqVO extends AliCaptchaAuthReqVO {
|
||||
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
@ApiModelProperty("手机号")
|
||||
private String phoneNumber;
|
||||
|
||||
@ApiModelProperty("图形验证码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("图形验证码唯一标识")
|
||||
private String uuid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package com.ruoyi.web.controller.xkt.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
public class AliCaptchaAuthReqVO {
|
||||
|
||||
@NotEmpty(message = "lot_number不能为空")
|
||||
@ApiModelProperty("lot_number(图像验证参数)")
|
||||
private String lot_number;
|
||||
|
||||
@NotEmpty(message = "captcha_output不能为空")
|
||||
@ApiModelProperty("captcha_output(图像验证参数)")
|
||||
private String captcha_output;
|
||||
|
||||
@NotEmpty(message = "pass_token不能为空")
|
||||
@ApiModelProperty("pass_token(图像验证参数)")
|
||||
private String pass_token;
|
||||
|
||||
@NotEmpty(message = "gen_time不能为空")
|
||||
@ApiModelProperty("gen_time(图像验证参数)")
|
||||
private String gen_time;
|
||||
|
||||
}
|
||||
|
|
@ -220,3 +220,9 @@ alipay:
|
|||
signType: RSA2
|
||||
charset: UTF-8
|
||||
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
||||
|
||||
# 阿里认证
|
||||
aliauth:
|
||||
captcha:
|
||||
appId: 386ec134856c9fe7d47ce2a34ee91038
|
||||
appKey: 1b4e3ff703ca1ea0fb802d188079a25c
|
||||
|
|
|
|||
|
|
@ -25,8 +25,4 @@ public class LoginCredential {
|
|||
|
||||
private String smsVerificationCode;
|
||||
|
||||
private String imgUuid;
|
||||
|
||||
private String imgVerificationCode;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,7 @@ public class SysLoginService {
|
|||
LoginUser loginUser;
|
||||
switch (loginCredential.getLoginType()) {
|
||||
case USERNAME:
|
||||
loginUser = loginByUsername(loginCredential.getUsername(), loginCredential.getPassword(),
|
||||
loginCredential.getImgVerificationCode(), loginCredential.getImgUuid());
|
||||
loginUser = loginByUsername(loginCredential.getUsername(), loginCredential.getPassword());
|
||||
break;
|
||||
case SMS_VERIFICATION_CODE:
|
||||
loginUser = loginBySmsVerificationCode(loginCredential.getPhoneNumber(),
|
||||
|
|
@ -115,14 +114,12 @@ public class SysLoginService {
|
|||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @param code 验证码
|
||||
* @param uuid 唯一标识
|
||||
* @return 结果
|
||||
*/
|
||||
private LoginUser loginByUsername(String username, String password, String code, String uuid) {
|
||||
private LoginUser loginByUsername(String username, String password) {
|
||||
|
||||
// 验证码校验
|
||||
validateCaptcha(username, code, uuid);
|
||||
// validateCaptcha(username, code, uuid);
|
||||
|
||||
// 登录前置校验
|
||||
loginPreCheck(username, password);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package com.ruoyi.xkt.manager;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.HmacAlgorithms;
|
||||
import org.apache.commons.codec.digest.HmacUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-07-22
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AliAuthManager {
|
||||
|
||||
private static final String CAPTCHA_URL = "https://captcha.alicaptcha.com/validate?captcha_id=%s";
|
||||
|
||||
@Value("${aliauth.captcha.appId:}")
|
||||
private String captchaId;
|
||||
@Value("${aliauth.captcha.appKey:}")
|
||||
private String captchaKey;
|
||||
|
||||
public boolean validate(String lotNumber, String captchaOutput, String passToken, String genTime) {
|
||||
if (StrUtil.isEmpty(lotNumber)
|
||||
|| StrUtil.isEmpty(captchaOutput)
|
||||
|| StrUtil.isEmpty(passToken)
|
||||
|| StrUtil.isEmpty(genTime)) {
|
||||
log.warn("图形认证参数异常: {}, {}, {}, {}", lotNumber, captchaOutput, passToken, genTime);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// 生成签名使用标准的hmac算法,使用用户当前完成验证的流水号lot_number作为原始消息message,使用客户验证私钥作为key
|
||||
// 采用sha256散列算法将message和key进行单向散列生成最终的签名
|
||||
String signToken = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, captchaKey).hmacHex(lotNumber);
|
||||
// 上传校验参数到验证服务二次验证接口, 校验用户验证状态
|
||||
// captcha_id 参数建议放在 url 后面, 方便请求异常时可以在日志中根据id快速定位到异常请求
|
||||
String url = String.format(CAPTCHA_URL, captchaId);
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header("Content-Type", "application/x-www-form-urlencoded");
|
||||
httpRequest.form("lot_number", lotNumber);
|
||||
httpRequest.form("captcha_output", captchaOutput);
|
||||
httpRequest.form("pass_token", passToken);
|
||||
httpRequest.form("gen_time", genTime);
|
||||
httpRequest.form("sign_token", signToken);
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("图形认证结果: {}", resBody);
|
||||
return "success".equals(JSON.parseObject(resBody).getString("result"));
|
||||
} catch (Exception e) {
|
||||
log.error("图形认证失败", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue