验证码

This commit is contained in:
songjinsheng 2022-06-16 09:24:27 +08:00
parent 2de946adb8
commit c9ee01dd1f
14 changed files with 598 additions and 108 deletions

View File

@ -29,4 +29,5 @@ public class RuoYiApplication
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -12,9 +12,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
/**
@ -34,6 +36,9 @@ public class SysLoginController
@Autowired
private SysPermissionService permissionService;
@Autowired
private TokenService tokenService;
/**
* 登录方法
*
@ -45,8 +50,7 @@ public class SysLoginController
{
AjaxResult ajax = AjaxResult.success();
// 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid());
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode());
ajax.put(Constants.TOKEN, token);
return ajax;
}
@ -59,7 +63,8 @@ public class SysLoginController
@GetMapping("getInfo")
public AjaxResult getInfo()
{
SysUser user = SecurityUtils.getLoginUser().getUser();
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合
@ -79,8 +84,10 @@ public class SysLoginController
@GetMapping("getRouters")
public AjaxResult getRouters()
{
Long userId = SecurityUtils.getUserId();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
// 用户信息
SysUser user = loginUser.getUser();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
return AjaxResult.success(menuService.buildMenus(menus));
}
}

View File

@ -1,10 +1,14 @@
package com.ruoyi.web.controller.yada;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.WeatherUtils;
import com.ruoyi.system.domain_yada.*;
import com.ruoyi.system.service_yada.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jdk.jfr.Frequency;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
@ -16,14 +20,20 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.spring.web.json.Json;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.http.HttpRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "/Special")
@ -55,7 +65,25 @@ public class SpecialController {
return IntoRegion(value);
}
/**
@RequestMapping(value = "/helpWeatherClass",method = {RequestMethod.GET})
public AjaxResult helpWeatherClass(String city,String type)
{
String url="https://restapi.amap.com/v3/weather/weatherInfo";
Map<String,String> map=new HashMap<>();
map.put("key","37087f0a3007dc67d37859553cd02d33");
map.put("city",city);
if (type!=null){ map.put("extensions",type);}
map.put("output","json");
String value= WeatherUtils.httpRequest(url,map);
WeatherUtilsVO vo = JSON.parseObject(value,WeatherUtilsVO.class);
// String value2=vo.getForecasts().substring(1,vo.getForecasts().length()-1);
// System.out.println(value2);
// vo.setForecast(JSON.parseObject(value2,ForecastVo.class));
// JSONObject userJson=JSONObject.parseObject(value);
// WeatherUtilsVO utilsValue= JSON.toJavaObject(userJson,WeatherUtilsVO.class);
return AjaxResult.success(vo);
} /**
* 森林覆盖率模板导入
*/
@RequestMapping(value = "/helpExcelAorest")

View File

@ -0,0 +1 @@
com.ruoyi.framework.web.service.CaptchaRedisService

View File

@ -3,9 +3,9 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 3.8.2
version: 3.4.0
# 版权年份
copyrightYear: 2022
copyrightYear: 2021
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
@ -25,13 +25,10 @@ server:
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数默认为100
accept-count: 1000
threads:
# tomcat最大线程数默认为200
max: 800
# Tomcat启动初始化的线程数默认值10
min-spare: 100
# tomcat最大线程数默认为200
max-threads: 800
# Tomcat启动初始化的线程数默认值25
min-spare-threads: 30
# 日志配置
logging:
@ -41,22 +38,19 @@ logging:
# Spring配置
spring:
# config:
# activate:
# on-profile: druid
profiles:
active: druid
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: druid
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
# 服务模块
devtools:
restart:
@ -69,9 +63,9 @@ spring:
# 端口默认为6379
port: 6379
# 数据库索引
database: 3
database: 0
# 密码
password: sdust2020
password:
# 连接超时时间
timeout: 10s
lettuce:
@ -87,42 +81,26 @@ spring:
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟
expireTime: 300
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: abcdefghijklmnopqrstuvwxyz
# 令牌有效期默认30分钟
expireTime: 30
# MyBatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain,com.ruoyi.**.domain_yada
# 配置mapper的扫描找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml,classpath*:mapper_yada/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
## 滑块验证码
#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
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
@ -133,12 +111,26 @@ swagger:
# 请求前缀
pathMapping: /dev-api
# 滑块验证码
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
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
excludes: /system/notice/*
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*

View File

@ -0,0 +1,66 @@
package com.ruoyi.common.utils.file;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;
import java.util.Map;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 9:17
*/
public class WeatherUtils
{
public static String httpRequest(String requestUrl,Map params) {
//buffer用于接受返回的字符
StringBuffer buffer = new StringBuffer();
try {
//建立URL把请求地址给补全其中urlencode方法用于把params里的参数给取出来
URL url = new URL(requestUrl+"?"+urlencode(params));
//打开http连接
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
//获得输入
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//将bufferReader的值给放到buffer里
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
//关闭bufferReader和输入流
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
//断开连接
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
//返回字符串
return buffer.toString();
}
public static String urlencode(Map<String,Object>data) {
//将map里的参数变成像 showapi_appid=###&showapi_sign=###&的样子
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}

View File

@ -35,13 +35,13 @@
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- &lt;!&ndash; 滑块验证码 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.github.anji-plus</groupId>-->
<!-- <artifactId>captcha-spring-boot-starter</artifactId>-->
<!-- <version>1.2.7</version>-->
<!-- </dependency>-->
<!-- 滑块验证码-->
<dependency>
<groupId>com.github.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId>
<version>1.2.7</version>
</dependency>
<!-- 验证码 -->
<dependency>

View File

@ -110,6 +110,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/login", "/captcha/get", "/captcha/check").permitAll()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证

View File

@ -0,0 +1,53 @@
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";
}
}

View File

@ -2,27 +2,27 @@ 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.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;
/**
@ -39,14 +39,12 @@ public class SysLoginService
@Resource
private AuthenticationManager authenticationManager;
@Autowired
private RedisCache redisCache;
@Autowired
private ISysUserService userService;
@Autowired
private ISysConfigService configService;
@Lazy
private CaptchaService captchaService;
/**
* 登录验证
@ -54,16 +52,18 @@ public class SysLoginService
* @param username 用户名
* @param password 密码
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public String login(String username, String password, String code, String uuid)
public String login(String username, String password, String code)
{
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
CaptchaVO captchaVO = new CaptchaVO();
captchaVO.setCaptchaVerification(code);
ResponseModel response = captchaService.verification(captchaVO);
if (!response.isSuccess())
{
validateCaptcha(username, code, uuid);
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
// 用户验证
Authentication authentication = null;
@ -88,36 +88,10 @@ public class SysLoginService
}
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 username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
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();
}
}
/**
* 记录登录信息
*

View File

@ -0,0 +1,110 @@
package com.ruoyi.system.domain_yada;
import java.time.LocalDate;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 10:04
*/
public class CastsVo
{
private String date;
private String week;
private String dayweather;
private String nightweather;
private String daytemp;
private String nighttemp;
private String daywind;
private String nightwind;
private String daypower;
private String nightpower;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getDayweather() {
return dayweather;
}
public void setDayweather(String dayweather) {
this.dayweather = dayweather;
}
public String getNightweather() {
return nightweather;
}
public void setNightweather(String nightweather) {
this.nightweather = nightweather;
}
public String getDaytemp() {
return daytemp;
}
public void setDaytemp(String daytemp) {
this.daytemp = daytemp;
}
public String getNighttemp() {
return nighttemp;
}
public void setNighttemp(String nighttemp) {
this.nighttemp = nighttemp;
}
public String getDaywind() {
return daywind;
}
public void setDaywind(String daywind) {
this.daywind = daywind;
}
public String getNightwind() {
return nightwind;
}
public void setNightwind(String nightwind) {
this.nightwind = nightwind;
}
public String getDaypower() {
return daypower;
}
public void setDaypower(String daypower) {
this.daypower = daypower;
}
public String getNightpower() {
return nightpower;
}
public void setNightpower(String nightpower) {
this.nightpower = nightpower;
}
}

View File

@ -0,0 +1,62 @@
package com.ruoyi.system.domain_yada;
import java.time.LocalDateTime;
import java.util.List;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 10:02
*/
public class ForecastVo {
private String city;
private String adcode;
private String province;
private String reporttime;
private List<CastsVo> casts;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAdcode() {
return adcode;
}
public void setAdcode(String adcode) {
this.adcode = adcode;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getReporttime() {
return reporttime;
}
public void setReporttime(String reporttime) {
this.reporttime = reporttime;
}
public List<CastsVo> getCasts() {
return casts;
}
public void setCasts(List<CastsVo> casts) {
this.casts = casts;
}
}

View File

@ -0,0 +1,110 @@
package com.ruoyi.system.domain_yada;
import java.time.LocalDateTime;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 9:57
*/
public class LivesVo
{
/**
* 省份名
*/
private String province;
/**
* 城市名
*/
private String city;
/**
* 区域编码
*/
private String adcode;
/**
*天气现象
*/
private String weather;
private String temperature;
private String winddirection;
private String windpower;
private String humidity;
private LocalDateTime reporttime;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAdcode() {
return adcode;
}
public void setAdcode(String adcode) {
this.adcode = adcode;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getWinddirection() {
return winddirection;
}
public void setWinddirection(String winddirection) {
this.winddirection = winddirection;
}
public String getWindpower() {
return windpower;
}
public void setWindpower(String windpower) {
this.windpower = windpower;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public LocalDateTime getReporttime() {
return reporttime;
}
public void setReporttime(LocalDateTime reporttime) {
this.reporttime = reporttime;
}
}

View File

@ -0,0 +1,85 @@
package com.ruoyi.system.domain_yada;
import java.util.List;
/**
* @Author: JinSheng Song
* @Date: 2022/6/10 9:53
*/
public class WeatherUtilsVO {
/**
* 接口返回状态
*/
private String status;
/**
* 返回结果数量
*/
private String count;
private String info;
private String infocode;
/**
* 实时天气预报
*/
private List<LivesVo> lives;
/**
* 预报天气
*/
private List<ForecastVo> forecasts;
// /**
// * 预报天气
// */
// private String forecasts;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getInfocode() {
return infocode;
}
public void setInfocode(String infocode) {
this.infocode = infocode;
}
public List<ForecastVo> getForecasts() {
return forecasts;
}
public void setForecasts(List<ForecastVo> forecasts) {
this.forecasts = forecasts;
}
public List<LivesVo> getLives() {
return lives;
}
public void setLives(List<LivesVo> lives) {
this.lives = lives;
}
}