宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見(jiàn)問(wèn)題
產(chǎn)品動(dòng)態(tài)
精選推薦

常用工具類(lèi)之AJ-Captcha入門(mén)

管理 管理 編輯 刪除

1.引入MAVEN依賴
若依官方引入的是1.2.7版本。我選擇了目前最常用的1.3.0版本。
在項(xiàng)目中給的 ruoyi-framework\pom.xml 添加依賴

<!-- anji滑塊驗(yàn)證碼 -->
    <dependency>
        <groupId>com.anji-plus</groupId>
        <artifactId>spring-boot-starter-captcha</artifactId>
        <version>1.3.0</version>
    </dependency>

2.修改application.yml,加入aj-captcha配置
在ruoyi-admin模塊中的application.yml中添加aj-captcha配置

spring.application.name=captcha-service
server.port=8088
 
# 滑動(dòng)驗(yàn)證,底圖路徑,不配置將使用默認(rèn)圖片
# 支持全路徑
# 支持項(xiàng)目路徑,以classpath:開(kāi)頭,取resource目錄下路徑,例:classpath:images/jigsaw
aj.captcha.jigsaw=classpath:images/jigsaw
# 滑動(dòng)驗(yàn)證,底圖路徑,不配置將使用默認(rèn)圖片
# 支持全路徑
# 支持項(xiàng)目路徑,以classpath:開(kāi)頭,取resource目錄下路徑,例:classpath:images/pic-click
aj.captcha.pic-click=classpath:images/pic-click
 
# 對(duì)于分布式部署的應(yīng)用,我們建議應(yīng)用自己實(shí)現(xiàn)CaptchaCacheService,比如用Redis或者memcache,
# 參考CaptchaCacheServiceRedisImpl.java
# 如果應(yīng)用是單點(diǎn)的,也沒(méi)有使用redis,那默認(rèn)使用內(nèi)存。
# 內(nèi)存緩存只適合單節(jié)點(diǎn)部署的應(yīng)用,否則驗(yàn)證碼生產(chǎn)與驗(yàn)證在節(jié)點(diǎn)之間信息不同步,導(dǎo)致失敗。
# !?。?注意啦,如果應(yīng)用有使用spring-boot-starter-data-redis,
# 請(qǐng)打開(kāi)CaptchaCacheServiceRedisImpl.java注釋。
# redis ----->  SPI: 在resources目錄新建META-INF.services文件夾(兩層),參考當(dāng)前服務(wù)resources。
# 緩存local/redis...
aj.captcha.cache-type=local
# local緩存的閾值,達(dá)到這個(gè)值,清除緩存
#aj.captcha.cache-number=1000
# local定時(shí)清除過(guò)期緩存(單位秒),設(shè)置為0代表不執(zhí)行
#aj.captcha.timing-clear=180
#spring.redis.host=10.108.11.46
#spring.redis.port=6379
#spring.redis.password=
#spring.redis.database=2
#spring.redis.timeout=6000
 
# 驗(yàn)證碼類(lèi)型default兩種都實(shí)例化。
aj.captcha.type=default
# 漢字統(tǒng)一使用Unicode,保證程序通過(guò)@value讀取到是中文,可通過(guò)這個(gè)在線轉(zhuǎn)換
# https://tool.chinaz.com/tools/unicode.aspx 中文轉(zhuǎn)Unicode
# 右下角水印文字(我的水印)
aj.captcha.water-mark=我的水印
# 右下角水印字體(不配置時(shí),默認(rèn)使用文泉驛正黑)
# 由于宋體等涉及到版權(quán),我們jar中內(nèi)置了開(kāi)源字體【文泉驛正黑】
# 方式一:直接配置OS層的現(xiàn)有的字體名稱(chēng),比如:宋體
# 方式二:自定義特定字體,請(qǐng)將字體放到工程resources下fonts文件夾,支持ttf\ttc\otf字體
# aj.captcha.water-font=WenQuanZhengHei.ttf
# 點(diǎn)選文字驗(yàn)證碼的文字字體(文泉驛正黑)
# aj.captcha.font-type=WenQuanZhengHei.ttf
# 校驗(yàn)滑動(dòng)拼圖允許誤差偏移量(默認(rèn)5像素)
aj.captcha.slip-offset=5
# aes加密坐標(biāo)開(kāi)啟或者禁用(true|false)
aj.captcha.aes-status=true
# 滑動(dòng)干擾項(xiàng)(0/1/2)
aj.captcha.interference-options=2
 
#點(diǎn)選字體樣式 默認(rèn)Font.BOLD
aj.captcha.font-style=1
#點(diǎn)選字體字體大小
aj.captcha.font-size=25
#點(diǎn)選文字個(gè)數(shù),存在問(wèn)題,暫不支持修改
#aj.captcha.click-word-count=4
 
 
aj.captcha.history-data-clear-enable=false
 
# 接口請(qǐng)求次數(shù)一分鐘限制是否開(kāi)啟 true|false
aj.captcha.req-frequency-limit-enable=false
# 驗(yàn)證失敗5次,get接口鎖定
aj.captcha.req-get-lock-limit=5
# 驗(yàn)證失敗后,鎖定時(shí)間間隔,s
aj.captcha.req-get-lock-seconds=360
# get接口一分鐘內(nèi)請(qǐng)求數(shù)限制
aj.captcha.req-get-minute-limit=30
# check接口一分鐘內(nèi)請(qǐng)求數(shù)限制
aj.captcha.req-check-minute-limit=30
# verify接口一分鐘內(nèi)請(qǐng)求數(shù)限制(暫用不上,可后臺(tái)直接調(diào)用captchaService)
#aj.captcha.req-verify-minute-limit=30

或者

# 滑塊驗(yàn)證碼
aj:
   captcha:
      # 緩存類(lèi)型
      cache-type: redis
      # blockPuzzle 滑塊 clickWord 文字點(diǎn)選  default默認(rèn)兩者都實(shí)例化
      type: blockPuzzle
      # 右下角顯示字
      water-mark: ruoyi.vip
      # 校驗(yàn)滑動(dòng)拼圖允許誤差偏移量(默認(rèn)5像素)
      slip-offset: 5
      # aes加密坐標(biāo)開(kāi)啟或者禁用(true|false)
      aes-status: true
      # 滑動(dòng)干擾項(xiàng)(0/1/2)
      interference-options: 2

這只是基礎(chǔ)配置,可以參考aj-captcha詳細(xì)配置選擇自己想用的參數(shù)。

在SecurityConfig中設(shè)置aj-captcha匿名訪問(wèn)權(quán)限
在 SecurityConfig.java 文件中configure方法下的httpSecurity添加如下語(yǔ)句:

.antMatchers("/captcha/get", "/captcha/check").anonymous()

修改后臺(tái)實(shí)現(xiàn)代碼
大家在修改代碼時(shí),切記不要按照文檔官方文檔直接覆蓋,建議使用文本比較工具將代碼進(jìn)行比對(duì)后只更新相關(guān)內(nèi)容,這也是開(kāi)發(fā)人員的良好習(xí)慣?。。?!

修改SysLoginService.java
抽離改動(dòng)點(diǎn)比較麻煩,大家自行去比對(duì)吧。主要改動(dòng)login方法。

import javax.annotation.Resource;
 
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
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.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
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.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
 
/**
 * 登錄校驗(yàn)方法
 *
 * @author ruoyi
 */
@Component
public class SysLoginService
{
    @Autowired
    private TokenService tokenService;
 
    @Resource
    private AuthenticationManager authenticationManager;
 
    @Autowired
    private RedisCache redisCache;
 
 
    @Autowired
    private ISysUserService userService;
 
    @Autowired
    private ISysConfigService configService;
 
    @Autowired
    @Lazy
    private CaptchaService captchaService;
    /**
     * 登錄驗(yàn)證
     *
     * @param username 用戶名
     * @param password 密碼
     * @param code 驗(yàn)證碼
     * @param uuid 唯一標(biāo)識(shí)
     * @return 結(jié)果
     */
    public String login(String username, String password, String code, String uuid)
    {
        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();
        }
        /*boolean captchaOnOff = configService.selectCaptchaOnOff();
        // 驗(yàn)證碼開(kāi)關(guān)
        if (captchaOnOff)
        {
            validateCaptcha(username, code, uuid);
        }*/
        // 用戶驗(yàn)證
        Authentication authentication = null;
        try
        {
            // 該方法會(huì)去調(diào)用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 ServiceException(e.getMessage());
            }
        }
        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);
    }
 
    /**
     * 校驗(yàn)驗(yàn)證碼
     *
     * @param username 用戶名
     * @param code 驗(yàn)證碼
     * @param uuid 唯一標(biāo)識(shí)
     * @return 結(jié)果
     */
   /* public void validateCaptcha(String username, String code, String uuid)
    {
        String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
        String captcha = redisCache.getCacheObject(verifyKey);
        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();
        }
    }
*/
    /**
     * 記錄登錄信息
     *
     * @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);
    }
}

新增 CaptchaRedisService.java

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驗(yàn)證碼緩存實(shí)現(xiàn)類(lèi)
 * 
 * @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";
    }
}

6.資源導(dǎo)入
將aj-captcha 官方提供的demo中的images包整體引入到resources包下。
文章的最上邊提供了下載地址,可自行下載。
至此,后端全部修改完畢。

7.修改前端
使用beyondcompare比較一下改動(dòng)內(nèi)容。

package.json
dependencies 增加

"crypto-js": "^4.1.1",

\src\views\login.vue
刪除原來(lái)的驗(yàn)證碼部分,增加滑塊驗(yàn)證碼相關(guān)代碼

<template>
  <div class="login">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
      <h3 class="title">若依后臺(tái)管理系統(tǒng)</h3>
      <el-form-item prop="username">
        <el-input
          v-model="loginForm.username"
          type="text"
          auto-complete="off"
          placeholder="賬號(hào)"
        >
          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          auto-complete="off"
          placeholder="密碼"
          @keyup.enter.native="handleLogin"
        >
          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
        </el-input>
      </el-form-item>
      <Verify
        @success="capctchaCheckSuccess"
        :mode="'pop'"
        :captchaType="'blockPuzzle'"
        :imgSize="{ width: '330px', height: '155px' }"
        ref="verify"
      ></Verify>
      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">記住密碼</el-checkbox>
      <el-form-item style="width:100%;">
        <el-button
          :loading="loading"
          size="medium"
          type="primary"
          style="width:100%;"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 錄</span>
          <span v-else>登 錄 中...</span>
        </el-button>
        <div style="float: right;" v-if="register">
          <router-link class="link-type" :to="'/register'">立即注冊(cè)</router-link>
        </div>
      </el-form-item>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
    </div>
  </div>
</template>
 
<script>
import Cookies from "js-cookie";
import { encrypt, decrypt } from '@/utils/jsencrypt'
import Verify from "@/components/Verifition/Verify";
 
export default {
  components: { Verify },
  name: "Login",
  data() {
    return {
      loginForm: {
        username: "admin",
        password: "admin123",
        rememberMe: false,
        code: "",
      },
      loginRules: {
        username: [
          { required: true, trigger: "blur", message: "請(qǐng)輸入您的賬號(hào)" }
        ],
        password: [
          { required: true, trigger: "blur", message: "請(qǐng)輸入您的密碼" }
        ],
      },
      loading: false,
      // 注冊(cè)開(kāi)關(guān)
      register: false,
      redirect: undefined
    };
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true
    }
  },
  created() {
    this.getCookie();
  },
  methods: {
 
    getCookie() {
      const username = Cookies.get("username");
      const password = Cookies.get("password");
      const rememberMe = Cookies.get('rememberMe')
      this.loginForm = {
        username: username === undefined ? this.loginForm.username : username,
        password: password === undefined ? this.loginForm.password : decrypt(password),
        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
      };
    },
    capctchaCheckSuccess(params) {
      this.loginForm.code = params.captchaVerification;
      this.loading = true;
      if (this.loginForm.rememberMe) {
        Cookies.set("username", this.loginForm.username, { expires: 30 });
        Cookies.set("password", encrypt(this.loginForm.password), { expires: 30, });
        Cookies.set("rememberMe", this.loginForm.rememberMe, { expires: 30 });
      } else {
        Cookies.remove("username");
        Cookies.remove("password");
        Cookies.remove("rememberMe");
      }
      this.$store.dispatch("Login", this.loginForm).then(() => {
          this.$router.push({ path: this.redirect || "/" }).catch(() => {});
        }).catch(() => {
          this.loading = false;
        });
    },
    handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.$refs.verify.show();
        }
      });
    }
  }
};
</script>
 
<style rel="stylesheet/scss" lang="scss">
.login {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background-image: url("../assets/images/login-background.jpg");
  background-size: cover;
}
.title {
  margin: 0px auto 30px auto;
  text-align: center;
  color: #707070;
}
 
.login-form {
  border-radius: 6px;
  background: #ffffff;
  width: 400px;
  padding: 25px 25px 5px 25px;
  .el-input {
    height: 38px;
    input {
      height: 38px;
    }
  }
  .input-icon {
    height: 39px;
    width: 14px;
    margin-left: 2px;
  }
}
.login-tip {
  font-size: 13px;
  text-align: center;
  color: #bfbfbf;
}
.login-code {
  width: 33%;
  height: 38px;
  float: right;
  img {
    cursor: pointer;
    vertical-align: middle;
  }
}
.el-login-footer {
  height: 40px;
  line-height: 40px;
  position: fixed;
  bottom: 0;
  width: 100%;
  text-align: center;
  color: #fff;
  font-family: Arial;
  font-size: 12px;
  letter-spacing: 1px;
}
.login-code-img {
  height: 38px;
}
</style>

其他資源
將 “集成aj-captcha實(shí)現(xiàn)滑塊驗(yàn)證碼\ruoyi-ui\src\“ 目錄下assets、components兩個(gè)目錄直接復(fù)制到項(xiàng)目中。
這就夠了。api目錄下文件用不到。

8.啟動(dòng)
1.建議先啟動(dòng)后端,再啟動(dòng)前端。
2.前后端都增加了依賴,后端需要更新maven依賴,前端更新crypto-js (npm install --save crypto-js)

最終效果如下:

0e8ef202306121736063459.gif


請(qǐng)登錄后查看

CRMEB-慕白寒窗雪 最后編輯于2023-06-12 17:36:25

快捷回復(fù)
回復(fù)
回復(fù)
回復(fù)({{post_count}}) {{!is_user ? '我的回復(fù)' :'全部回復(fù)'}}
排序 默認(rèn)正序 回復(fù)倒序 點(diǎn)贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無(wú)簡(jiǎn)介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復(fù) {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)
查看更多
打賞
已打賞¥{{reward_price}}
2126
{{like_count}}
{{collect_count}}
添加回復(fù) ({{post_count}})

相關(guān)推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見(jiàn)問(wèn)題 產(chǎn)品動(dòng)態(tài) 精選推薦 首頁(yè)頭條 首頁(yè)動(dòng)態(tài) 首頁(yè)推薦
取 消 確 定
回復(fù)
回復(fù)
問(wèn)題:
問(wèn)題自動(dòng)獲取的帖子內(nèi)容,不準(zhǔn)確時(shí)需要手動(dòng)修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當(dāng)前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請(qǐng)輸入 0.1-{{reward_max_price}} 范圍內(nèi)的數(shù)值
打賞成功
¥{{price}}
完成 確認(rèn)打賞

微信登錄/注冊(cè)

切換手機(jī)號(hào)登錄

{{ bind_phone ? '綁定手機(jī)' : '手機(jī)登錄'}}

{{codeText}}
切換微信登錄/注冊(cè)
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開(kāi)源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服