pull/1121/head
parent
56f8abbc12
commit
d641eb102a
|
|
@ -135,6 +135,8 @@ public class StoreUserController extends BaseController {
|
||||||
Assert.notNull(storeId);
|
Assert.notNull(storeId);
|
||||||
Assert.notEmpty(vo.getPhonenumber(), "用户手机号不能为空");
|
Assert.notEmpty(vo.getPhonenumber(), "用户手机号不能为空");
|
||||||
Set<Long> subRoleIds = roleService.getSubRoleIdsByStore(storeId);
|
Set<Long> subRoleIds = roleService.getSubRoleIdsByStore(storeId);
|
||||||
|
CollUtil.emptyIfNull(vo.getRoleIds())
|
||||||
|
.forEach(roleId -> Assert.isTrue(subRoleIds.contains(roleId), "角色非法"));
|
||||||
UserInfo info = userService.getUserByPhoneNumber(vo.getPhonenumber());
|
UserInfo info = userService.getUserByPhoneNumber(vo.getPhonenumber());
|
||||||
Assert.notNull(info, "用户不存在");
|
Assert.notNull(info, "用户不存在");
|
||||||
List<Long> roleIds = new ArrayList<>();
|
List<Long> roleIds = new ArrayList<>();
|
||||||
|
|
@ -153,8 +155,8 @@ public class StoreUserController extends BaseController {
|
||||||
}
|
}
|
||||||
UserInfoEdit dto = BeanUtil.toBean(info, UserInfoEdit.class);
|
UserInfoEdit dto = BeanUtil.toBean(info, UserInfoEdit.class);
|
||||||
roleIds.addAll(CollUtil.emptyIfNull(vo.getRoleIds()));
|
roleIds.addAll(CollUtil.emptyIfNull(vo.getRoleIds()));
|
||||||
dto.setUserName(vo.getUserName());
|
|
||||||
dto.setRoleIds(roleIds);
|
dto.setRoleIds(roleIds);
|
||||||
|
dto.setUserName(vo.getUserName());
|
||||||
Long userId = userService.updateUser(dto);
|
Long userId = userService.updateUser(dto);
|
||||||
// 清除用户缓存(退出登录)
|
// 清除用户缓存(退出登录)
|
||||||
tokenService.deleteCacheUser(userId);
|
tokenService.deleteCacheUser(userId);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.ruoyi.system.service.ISysMenuService;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
import com.ruoyi.web.controller.system.vo.*;
|
import com.ruoyi.web.controller.system.vo.*;
|
||||||
|
import com.ruoyi.xkt.manager.AliAuthManager;
|
||||||
import com.ruoyi.xkt.service.IStoreService;
|
import com.ruoyi.xkt.service.IStoreService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
|
@ -59,6 +60,8 @@ public class SysLoginController {
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
@Autowired
|
||||||
|
private AliAuthManager aliAuthManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录方法
|
* 登录方法
|
||||||
|
|
@ -69,14 +72,17 @@ public class SysLoginController {
|
||||||
@ApiOperation(value = "用户名密码登录")
|
@ApiOperation(value = "用户名密码登录")
|
||||||
@PostMapping("/loginByUname")
|
@PostMapping("/loginByUname")
|
||||||
public AjaxResult login(@Validated @RequestBody LoginByUsernameVO loginBody) {
|
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();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
// 生成令牌
|
// 生成令牌
|
||||||
LoginCredential credential = LoginCredential.builder()
|
LoginCredential credential = LoginCredential.builder()
|
||||||
.loginType(ELoginType.USERNAME)
|
.loginType(ELoginType.USERNAME)
|
||||||
.username(loginBody.getUsername())
|
.username(loginBody.getUsername())
|
||||||
.password(loginBody.getPassword())
|
.password(loginBody.getPassword())
|
||||||
.imgUuid(loginBody.getUuid())
|
|
||||||
.imgVerificationCode(loginBody.getCode())
|
|
||||||
.build();
|
.build();
|
||||||
String token = loginService.login(credential);
|
String token = loginService.login(credential);
|
||||||
ajax.put(Constants.TOKEN, token);
|
ajax.put(Constants.TOKEN, token);
|
||||||
|
|
@ -101,7 +107,12 @@ public class SysLoginController {
|
||||||
@ApiOperation(value = "发送登录短信验证码")
|
@ApiOperation(value = "发送登录短信验证码")
|
||||||
@PostMapping("/sendSmsVerificationCode")
|
@PostMapping("/sendSmsVerificationCode")
|
||||||
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
|
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();
|
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.LoginSmsReqVO;
|
||||||
import com.ruoyi.web.controller.system.vo.RegisterBySmsCodeVO;
|
import com.ruoyi.web.controller.system.vo.RegisterBySmsCodeVO;
|
||||||
import com.ruoyi.web.controller.xkt.vo.PhoneNumberVO;
|
import com.ruoyi.web.controller.xkt.vo.PhoneNumberVO;
|
||||||
|
import com.ruoyi.xkt.manager.AliAuthManager;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -45,6 +46,9 @@ public class SysRegisterController extends BaseController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysUserService userService;
|
private ISysUserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AliAuthManager aliAuthManager;
|
||||||
|
|
||||||
@ApiOperation(value = "档口供应商注册")
|
@ApiOperation(value = "档口供应商注册")
|
||||||
@PostMapping("/registerStore")
|
@PostMapping("/registerStore")
|
||||||
public AjaxResult registerStore(@Validated @RequestBody RegisterBySmsCodeVO vo) {
|
public AjaxResult registerStore(@Validated @RequestBody RegisterBySmsCodeVO vo) {
|
||||||
|
|
@ -90,7 +94,12 @@ public class SysRegisterController extends BaseController {
|
||||||
@ApiOperation(value = "发送登录短信验证码")
|
@ApiOperation(value = "发送登录短信验证码")
|
||||||
@PostMapping("/sendSmsVerificationCode")
|
@PostMapping("/sendSmsVerificationCode")
|
||||||
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
|
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();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package com.ruoyi.web.controller.system.vo;
|
package com.ruoyi.web.controller.system.vo;
|
||||||
|
|
||||||
|
import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
|
@ -12,7 +15,9 @@ import javax.validation.constraints.NotEmpty;
|
||||||
*/
|
*/
|
||||||
@ApiModel
|
@ApiModel
|
||||||
@Data
|
@Data
|
||||||
public class LoginByUsernameVO {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class LoginByUsernameVO extends AliCaptchaAuthReqVO {
|
||||||
/**
|
/**
|
||||||
* 用户名
|
* 用户名
|
||||||
*/
|
*/
|
||||||
|
|
@ -26,16 +31,4 @@ public class LoginByUsernameVO {
|
||||||
@NotEmpty(message = "用户密码不能为空")
|
@NotEmpty(message = "用户密码不能为空")
|
||||||
@ApiModelProperty(value = "用户密码", required = true)
|
@ApiModelProperty(value = "用户密码", required = true)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证码
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("图形验证码")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 唯一标识
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("图形验证码唯一标识")
|
|
||||||
private String uuid;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package com.ruoyi.web.controller.system.vo;
|
package com.ruoyi.web.controller.system.vo;
|
||||||
|
|
||||||
|
import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
@ -13,16 +16,12 @@ import javax.validation.constraints.Pattern;
|
||||||
*/
|
*/
|
||||||
@ApiModel
|
@ApiModel
|
||||||
@Data
|
@Data
|
||||||
public class LoginSmsReqVO {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class LoginSmsReqVO extends AliCaptchaAuthReqVO {
|
||||||
|
|
||||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
||||||
@NotEmpty(message = "手机号不能为空")
|
@NotEmpty(message = "手机号不能为空")
|
||||||
@ApiModelProperty("手机号")
|
@ApiModelProperty("手机号")
|
||||||
private String phoneNumber;
|
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
|
signType: RSA2
|
||||||
charset: UTF-8
|
charset: UTF-8
|
||||||
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
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 smsVerificationCode;
|
||||||
|
|
||||||
private String imgUuid;
|
|
||||||
|
|
||||||
private String imgVerificationCode;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,7 @@ public class SysLoginService {
|
||||||
LoginUser loginUser;
|
LoginUser loginUser;
|
||||||
switch (loginCredential.getLoginType()) {
|
switch (loginCredential.getLoginType()) {
|
||||||
case USERNAME:
|
case USERNAME:
|
||||||
loginUser = loginByUsername(loginCredential.getUsername(), loginCredential.getPassword(),
|
loginUser = loginByUsername(loginCredential.getUsername(), loginCredential.getPassword());
|
||||||
loginCredential.getImgVerificationCode(), loginCredential.getImgUuid());
|
|
||||||
break;
|
break;
|
||||||
case SMS_VERIFICATION_CODE:
|
case SMS_VERIFICATION_CODE:
|
||||||
loginUser = loginBySmsVerificationCode(loginCredential.getPhoneNumber(),
|
loginUser = loginBySmsVerificationCode(loginCredential.getPhoneNumber(),
|
||||||
|
|
@ -115,14 +114,12 @@ public class SysLoginService {
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param password 密码
|
* @param password 密码
|
||||||
* @param code 验证码
|
|
||||||
* @param uuid 唯一标识
|
|
||||||
* @return 结果
|
* @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);
|
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