warn: 修改配置文件
1、修改 配置信息 获取方式
2、调整原验证码 相关配置信息
3、新增多种验证码 方式
pull/403/head
廖金龙 2020-06-10 19:10:00 +08:00
parent 9b8b01c55c
commit 84c03cacd5
13 changed files with 466 additions and 39 deletions

View File

@ -0,0 +1,98 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.exception;
/**
*
*
* @author: liaojinlong
* @date: 2020/6/10 18:06
*/
public class BadConfigurationException extends RuntimeException {
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public BadConfigurationException() {
super();
}
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public BadConfigurationException(String message) {
super(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new runtime exception with the specified cause and a
* detail message of {@code (cause==null ? null : cause.toString())}
* (which typically contains the class and detail message of
* {@code cause}). This constructor is useful for runtime exceptions
* that are little more than wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(Throwable cause) {
super(cause);
}
/**
* Constructs a new runtime exception with the specified detail
* message, cause, suppression enabled or disabled, and writable
* stack trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config;
import me.zhengjie.modules.security.config.bean.LoginProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @apiNote Pojo
* @author: liaojinlong
* @date: 2020/6/10 19:04
*/
@Configuration
public class ConfigBeanConfiguration {
@Bean
@ConfigurationProperties(prefix = "login", ignoreUnknownFields = true)
public LoginProperties loginProperties() {
return new LoginProperties();
}
@Bean
@ConfigurationProperties(prefix = "jwt", ignoreUnknownFields = true)
public SecurityProperties securityProperties() {
return new SecurityProperties();
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config.bean;
/**
*
*
* @author: liaojinlong
* @date: 2020/6/10 18:53
*/
public class LoginCode {
/**
*
*/
private LoginCodeEnum codeType;
/**
*
*/
private Long expiration = 2L;
/**
*
*/
private int length = 2;
/**
*
*/
private int width = 111;
/**
*
*/
private int height = 36;
public LoginCodeEnum getCodeType() {
return codeType;
}
public void setCodeType(LoginCodeEnum codeType) {
this.codeType = codeType;
}
public Long getExpiration() {
return expiration;
}
public void setExpiration(Long expiration) {
this.expiration = expiration;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config.bean;
/**
*
*
* @author: liaojinlong
* @date: 2020/6/10 17:40
*/
public enum LoginCodeEnum {
/**
*
*/
arithmetic,
/**
*
*/
chinese,
/**
*
*/
chinese_gif,
/**
*
*/
gif,
spec
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* Licensed under the Apache License, Version loginCode.length.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-loginCode.length.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config.bean;
import com.wf.captcha.*;
import com.wf.captcha.base.Captcha;
import me.zhengjie.exception.BadConfigurationException;
import java.util.Objects;
/**
*
*
* @author: liaojinlong
* @date: loginCode.length0loginCode.length0/6/10 17:loginCode.length6
*/
public class LoginProperties {
/**
*
*/
private boolean singleLogin = false;
private LoginCode loginCode;
public boolean isSingleLogin() {
return singleLogin;
}
public void setSingleLogin(boolean singleLogin) {
this.singleLogin = singleLogin;
}
public LoginCode getLoginCode() {
return loginCode;
}
public void setLoginCode(LoginCode loginCode) {
this.loginCode = loginCode;
}
/**
*
*
* @return /
*/
public Captcha getCaptcha() {
if (Objects.isNull(loginCode)) {
loginCode = new LoginCode();
if (Objects.isNull(loginCode.getCodeType())) {
loginCode.setCodeType(LoginCodeEnum.arithmetic);
}
}
Captcha captcha = switchCaptcha(loginCode);
return captcha;
}
/**
*
*
* @param loginCode
* @return /
*/
private Captcha switchCaptcha(LoginCode loginCode) {
Captcha captcha;
synchronized (this) {
switch (loginCode.getCodeType()) {
case arithmetic:
// 算术类型 https://gitee.com/whvse/EasyCaptcha
captcha = new ArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight());
// 几位数运算,默认是两位
captcha.setLen(loginCode.getLength());
break;
case chinese:
captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case chinese_gif:
captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case gif:
captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
case spec:
captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
default:
throw new BadConfigurationException("验证码配置信息错误!!!正确配置查看 me.zhengjie.modules.security.config.bean.LoginCodeEnum ");
}
}
return captcha;
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.security.config;
package me.zhengjie.modules.security.config.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -21,36 +21,51 @@ import org.springframework.context.annotation.Configuration;
/**
* Jwt
*
* @author Zheng Jie
* @date 20191128
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class SecurityProperties {
/** Request Headers Authorization */
/**
* Request Headers Authorization
*/
private String header;
/** 令牌前缀,最后留个空格 Bearer */
/**
* Bearer
*/
private String tokenStartWith;
/** 必须使用最少88位的Base64对该令牌进行编码 */
/**
* 使88Base64
*/
private String base64Secret;
/** 令牌过期时间 此处单位/毫秒 */
/**
* /
*/
private Long tokenValidityInSeconds;
/** 在线用户 key根据 key 查询 redis 中在线用户的数据 */
/**
* 线 key key redis 线
*/
private String onlineKey;
/** 验证码 key */
/**
* key
*/
private String codeKey;
/** token 续期检查 */
/**
* token
*/
private Long detect;
/** 续期时间 */
/**
*
*/
private Long renew;
public String getTokenStartWith() {

View File

@ -17,6 +17,7 @@ package me.zhengjie.modules.security.rest;
import cn.hutool.core.util.IdUtil;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@ -27,7 +28,8 @@ import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.annotation.rest.AnonymousPostMapping;
import me.zhengjie.config.RsaProperties;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.config.bean.LoginProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.modules.security.security.TokenProvider;
import me.zhengjie.modules.security.service.dto.AuthUserDto;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
@ -46,6 +48,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@ -62,16 +65,13 @@ import java.util.concurrent.TimeUnit;
@RequiredArgsConstructor
@Api(tags = "系统:系统授权接口")
public class AuthorizationController {
@Value("${loginCode.expiration}")
private Long expiration;
@Value("${single.login}")
private Boolean singleLogin;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
private final OnlineUserService onlineUserService;
private final TokenProvider tokenProvider;
private final AuthenticationManagerBuilder authenticationManagerBuilder;
@Resource
private LoginProperties loginProperties;
@Log("用户登录")
@ApiOperation("登录授权")
@ -104,7 +104,7 @@ public class AuthorizationController {
put("token", properties.getTokenStartWith() + token);
put("user", jwtUserDto);
}};
if (singleLogin) {
if (loginProperties.isSingleLogin()) {
//踢掉之前已经登录的token
onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
}
@ -120,15 +120,11 @@ public class AuthorizationController {
@ApiOperation("获取验证码")
@AnonymousGetMapping(value = "/code")
public ResponseEntity<Object> getCode() {
// 算术类型 https://gitee.com/whvse/EasyCaptcha
ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);
// 几位数运算,默认是两位
captcha.setLen(2);
// 获取运算的结果
String result = captcha.text();
Captcha captcha = loginProperties.getCaptcha();
String uuid = properties.getCodeKey() + IdUtil.simpleUUID();
// 保存
redisUtils.set(uuid, result, expiration, TimeUnit.MINUTES);
redisUtils.set(uuid, captcha.text(), loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
// 验证码信息
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
put("img", captcha.toBase64());

View File

@ -19,7 +19,7 @@ import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.modules.security.service.dto.OnlineUserDto;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.utils.SpringContextHolder;

View File

@ -24,7 +24,7 @@ import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.utils.RedisUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

View File

@ -16,7 +16,7 @@
package me.zhengjie.modules.security.service;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.config.SecurityProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.security.service.dto.OnlineUserDto;
import me.zhengjie.utils.*;

View File

@ -6,7 +6,7 @@ spring:
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: 59421
password: 123456
# 初始连接数
initial-size: 5
# 最小连接数
@ -44,9 +44,22 @@ spring:
config:
multi-statement-allow: true
# 是否限制单用户登录
single:
login: false
# 登录相关配置
login:
# 是否限制单用户登录
single: false
# 验证码
login-code:
# 验证码类型配置
code-type: chinese_gif
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
heigth: 36
# 内容长度
length: 3
#jwt
jwt:

View File

@ -46,9 +46,22 @@ spring:
config:
multi-statement-allow: true
# 是否限制单用户登录
single:
login: false
# 登录相关配置
login:
# 是否限制单用户登录
single: false
# 验证码
login-code:
# 验证码类型配置
code-type: chinese_gif
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
heigth: 36
# 内容长度
length: 3
#jwt
jwt:
@ -100,4 +113,4 @@ file:
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
avatarMaxSize: 5

View File

@ -50,9 +50,22 @@ qiniu:
code:
expiration: 300
#登录图形验证码有效时间/分钟
loginCode:
expiration: 2
# 登录相关配置
login:
# 是否限制单用户登录
single: false
# 验证码
login-code:
# 验证码类型配置
code-type: chinese_gif
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
heigth: 36
# 内容长度
length: 3
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
@ -60,4 +73,4 @@ rsa:
# sm.ms 图床的 token
smms:
token: 1oOP3ykFDI0K6ifmtvU7c8Y1eTWZSlyl
token: 1oOP3ykFDI0K6ifmtvU7c8Y1eTWZSlyl