开发喵星球

若依分离版集成aj-captcha实现滑块验证码(五十六)

1、ruoyi-framework\pom.xm`添加依赖

<!-- 滑块验证码  -->
<dependency>
    <groupId>com.github.anji-plus</groupId>
    <artifactId>captcha-spring-boot-starter</artifactId>
    <version>1.2.7</version>
</dependency>

<!-- 原有的验证码kaptcha依赖不需要可以删除  -->

2、修改application.yml,加入aj-captcha配置

# 滑块验证码
aj:
   captcha:
      # 缓存类型
      cache-type: redis
      # blockPuzzle 滑块 clickWord 文字点选  default默认两者都实例化
      type: blockPuzzle
      # 右下角显示字
      water-mark: ruoyi.vip
      # 校验滑动拼图允许误差偏移量(默认5像素)
      slip-offset: 5
      # aes加密坐标开启或者禁用(true|false)
      aes-status: true
      # 滑动干扰项(0/1/2)
      interference-options: 2

同时在ruoyi-admin\src\main\resources\META-INF\services下创建com.anji.captcha.service.CaptchaCacheService文件同时设置文件内容为

com.ruoyi.framework.web.service.CaptchaRedisService

3、在SecurityConfig中设置httpSecurity配置匿名访问

.antMatchers("/login", "/captcha/get", "/captcha/check").permitAll()

4、修改相关类

移除原先不需要的类
ruoyi-admin\com\ruoyi\web\controller\common\CaptchaController.java
ruoyi-framework\com\ruoyi\framework\config\CaptchaConfig.java
ruoyi-framework\com\ruoyi\framework\config\KaptchaTextCreator.java

修改ruoyi-admin\com\ruoyi\web\controller\system\SysLoginController.java

/**
 * 登录方法
 * 
 * @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());
    ajax.put(Constants.TOKEN, token);
    return ajax;
}

修改ruoyi-framework\com\ruoyi\framework\web\service\SysLoginService.java

package com.ruoyi.framework.web.service;

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysUserService;

/**
 * 登录校验方法
 * 
 * @author ruoyi
 */
@Component
public class SysLoginService
{
    @Autowired
    private TokenService tokenService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private ISysUserService userService;

    @Autowired
    @Lazy
    private CaptchaService captchaService;

    /**
     * 登录验证
     * 
     * @param username 用户名
     * @param password 密码
     * @param code 验证码
     * @return 结果
     */
    public String login(String username, String password, String code)
    {
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(code);
        ResponseModel response = captchaService.verification(captchaVO);
        if (!response.isSuccess())
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        // 用户验证
        Authentication authentication = null;
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        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 ServiceException(e.getMessage());
            }
        }
        finally
        {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }
}

新增 ruoyi-framework\com\ruoyi\framework\web\service\CaptchaRedisService.java

package com.ruoyi.framework.web.service;

import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import com.anji.captcha.service.CaptchaCacheService;

/**
 * 自定义redis验证码缓存实现类
 * 
 * @author ruoyi
 */
public class CaptchaRedisService implements CaptchaCacheService
{
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void set(String key, String value, long expiresInSeconds)
    {
        stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
    }

    @Override
    public boolean exists(String key)
    {
        return stringRedisTemplate.hasKey(key);
    }

    @Override
    public void delete(String key)
    {
        stringRedisTemplate.delete(key);
    }

    @Override
    public String get(String key)
    {
        return stringRedisTemplate.opsForValue().get(key);
    }

    @Override
    public Long increment(String key, long val)
    {
        return stringRedisTemplate.opsForValue().increment(key, val);
    }

    @Override
    public String type()
    {
        return "redis";
    }
}

5、添加滑动验证码插件到ruoyi-ui

下载前端插件相关包和代码实现ruoyi-vue/集成滑动验证码.zip

链接: https://pan.baidu.com/s/13JVC9jm-Dp9PfHdDDylLCQ
提取码: y9jt

   
分类:Java/OOP 作者:无限繁荣, 吴蓉 发表于:2023-11-30 17:30:57 阅读量:274
<<   >>


powered by kaifamiao