Merge branch 'source'

# Conflicts:
#	eladmin-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginProperties.java
#	eladmin-system/src/main/resources/config/application-dev.yml
#	eladmin-system/src/main/resources/config/application-prod.yml
#	eladmin-system/src/main/resources/config/application.yml
pull/411/head
廖金龙 2020-06-10 21:11:25 +08:00
commit a5fc181b3f
7 changed files with 150 additions and 45 deletions

View File

@ -0,0 +1,74 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* 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.utils.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author Zheng Jie
* @website https://el-admin.vip
* @description
* @date 2020-06-10
**/
@Getter
@AllArgsConstructor
public enum RequestMethodEnum {
/**
* @AnonymousGetMapping
*/
GET("GET"),
/**
* @AnonymousPostMapping
*/
POST("POST"),
/**
* @AnonymousPutMapping
*/
PUT("PUT"),
/**
* @AnonymousPatchMapping
*/
PATCH("PATCH"),
/**
* @AnonymousDeleteMapping
*/
DELETE("DELETE"),
/**
* Request
*/
ALL("All");
/**
* Request
*/
private final String type;
public static RequestMethodEnum find(String type) {
for (RequestMethodEnum value : RequestMethodEnum.values()) {
if (type.equals(value.getType())) {
return value;
}
}
return ALL;
}
}

View File

@ -18,6 +18,7 @@ package me.zhengjie.modules.security.config;
import lombok.RequiredArgsConstructor;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.modules.security.security.*;
import me.zhengjie.utils.enums.RequestMethodEnum;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -31,13 +32,12 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* @author Zheng Jie
@ -70,14 +70,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity httpSecurity) throws Exception {
// 搜寻匿名标记 url @AnonymousAccess
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Set<String> anonymousUrls = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess) {
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
}
}
// 获取匿名标记
Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);
httpSecurity
// 禁用 CSRF
.csrf().disable()
@ -86,18 +80,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.exceptionHandling()
.authenticationEntryPoint(authenticationErrorHandler)
.accessDeniedHandler(jwtAccessDeniedHandler)
// 防止iframe 造成跨域
.and()
.headers()
.frameOptions()
.disable()
// 不创建会话
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 静态资源等等
@ -121,13 +112,69 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/druid/**").permitAll()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 自定义匿名访问所有url放行 允许匿名和带权限以及登录用户访问
.antMatchers(anonymousUrls.toArray(new String[0])).permitAll()
// 自定义匿名访问所有url放行允许匿名和带Token访问细腻化到每个 Request 类型
// GET
.antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
// POST
.antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
// PUT
.antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
// PATCH
.antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
// DELETE
.antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
// 所有类型的接口都放行
.antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
// 所有请求都需要认证
.anyRequest().authenticated()
.and().apply(securityConfigurerAdapter());
}
private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
Map<String, Set<String>> anonymousUrls = new HashMap<>(6);
Set<String> get = new HashSet<>();
Set<String> post = new HashSet<>();
Set<String> put = new HashSet<>();
Set<String> patch = new HashSet<>();
Set<String> delete = new HashSet<>();
Set<String> all = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess) {
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
switch (Objects.requireNonNull(request)){
case GET:
get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case POST:
post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PUT:
put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PATCH:
patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case DELETE:
delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
default:
all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
}
}
}
anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
return anonymousUrls;
}
private TokenConfigurer securityConfigurerAdapter() {
return new TokenConfigurer(tokenProvider);
}

View File

@ -19,14 +19,12 @@ 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
* @author liaojinlong
* @date loginCode.length0loginCode.length0/6/10 17:loginCode.length6
*/
public class LoginProperties {
@ -65,8 +63,7 @@ public class LoginProperties {
loginCode.setCodeType(LoginCodeEnum.arithmetic);
}
}
Captcha captcha = switchCaptcha(loginCode);
return captcha;
return switchCaptcha(loginCode);
}
/**
@ -100,6 +97,7 @@ public class LoginProperties {
case spec:
captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
captcha.setLen(loginCode.getLength());
break;
default:
throw new BadConfigurationException("验证码配置信息错误!!!正确配置查看 me.zhengjie.modules.security.config.bean.LoginCodeEnum ");
}

View File

@ -109,6 +109,10 @@ public class UserServiceImpl implements UserService {
redisUtils.del("menu::user:" + resources.getId());
redisUtils.del("role::auth:" + resources.getId());
}
// 如果用户名称修改
if(!resources.getUsername().equals(user.getUsername())){
redisUtils.del("user::username:" + user.getUsername());
}
user.setUsername(resources.getUsername());
user.setEmail(resources.getEmail());
user.setEnabled(resources.getEnabled());

View File

@ -50,8 +50,8 @@ login:
single: false
# 验证码
login-code:
# 验证码类型配置
code-type: chinese_gif
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
@ -59,7 +59,7 @@ login:
# 验证码宽度
heigth: 36
# 内容长度
length: 3
length: 2
#jwt
jwt:
@ -91,7 +91,6 @@ swagger:
ip:
local-parsing: true
# 文件存储路径
file:
mac:

View File

@ -52,7 +52,7 @@ login:
single: false
# 验证码
login-code:
# 验证码类型配置
# 验证码类型配置 查看 LoginProperties 类
code-type: chinese_gif
# 登录图形验证码有效时间/分钟
expiration: 2
@ -61,7 +61,7 @@ login:
# 验证码宽度
heigth: 36
# 内容长度
length: 3
length: 2
#jwt
jwt:

View File

@ -50,23 +50,6 @@ qiniu:
code:
expiration: 300
# 登录相关配置
login:
# 是否限制单用户登录
single: false
# 验证码
login-code:
# 验证码类型配置
code-type: chinese_gif
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
heigth: 36
# 内容长度
length: 3
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==