验证码登录实现


 在用户登录的时候,需要做安全校验,加验证码是普遍的做法,分析一下ruoyi开源框架的验证码登录实现逻辑

当用户打开登录页面的时候,就要发送请求,去后台生成一个验证码传到前台

1.

@RestController
public class CaptchaController { @Autowired private RedisService redisService; /** * 生成验证码工具类 */ @GetMapping("/creatorCode") public Result creatorCode(HttpServletResponse response) throws IOException { // 生成验证码随机4位字符串 String verifyCode = VerifyCodeUtils.generateVerifyCode(4); // 生成uuid 17ce79633eea49f6a1d4035505078fd8 String uuid = UuIdUtils.createUUID(); //生成的UUID,加上captcha_codes:最为键,当做redis中的key存储code String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; redisCache.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); // 生成图片 int w = 111, h = 36; ByteArrayOutputStream stream = new ByteArrayOutputStream(); VerifyCodeUtils.outputImage(w, h, stream, verifyCode); try { AjaxResult ajax = AjaxResult.success(); ajax.put("uuid", uuid); ajax.put("img", Base64.encode(stream.toByteArray())); return ajax; } catch (Exception e) { e.printStackTrace(); return AjaxResult.error(e.getMessage()); } finally { stream.close(); } } }
//已生成的Key和对应的Value

 

 

 

2.用户输入账号密码验证码,发送请求到后端进行校验 访问:http://localhost/login

/**
 * 登录方法
 * @param loginBody 登陆信息
 * @return 结果
 */
@PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { AjaxResult ajax = AjaxResult.success(); // 生成令牌 String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid()); ajax.put(Constants.TOKEN, token); return ajax; }

SysLoginService 这个类会进行用户信息的校@Component
public class SysLoginService
{
@Autowired
private TokenService tokenService;

@Resource
private AuthenticationManager authenticationManager;

@Autowired
private RedisCache redisCache;

/**
* 登录验证
*
* @param username 用户名
* @param password 密码
* @param captcha 验证码
* @param uuid 唯一标识
* @return 结果
*/
public String login(String username, String password, String code, String uuid)
{
         //用户携带过来的:uuid17ce79633eea49f6a1d4035505078fd8
      //当登录页面打开的时候,这个uuid和验证码就已经携带发送给页面
System.out.println("用户携带过来的UUID:"+uuid);
    
     //拿到uuid拼接Constants.CAPTCHA_CODE_KEY
     String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
//拿到拼接后的数据作为条件查询redis
String captcha = redisCache.getCacheObject(verifyKey);
     //redis中删除验证码
redisCache.deleteObject(verifyKey);
        //校验验证码
if (captcha == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
// 用户验证
Authentication authentication = null;
try
{
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (Exception e)
{
if (e instanceof BadCredentialsException)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
}
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
throw new CustomException(e.getMessage());
}
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
      //校验完成后得到 loginUser对象, 基于这个对象生成token,完成登录
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
// 生成token
return tokenService.createToken(loginUser);
}
}

 

自己一些小总结,还在学习阶段

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM