Compare commits
3
Commits
55143e9d8d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f3f2f987c | ||
|
|
d9f709de3d | ||
|
|
94d72c5f46 |
@@ -0,0 +1,22 @@
|
|||||||
|
package com.gw.test.config;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.Components;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class OpenApiConfig {
|
||||||
|
@Bean
|
||||||
|
public OpenAPI api() {
|
||||||
|
return new OpenAPI().info(new Info().title("Test").version("v1.0.0").description( "接口测试"))
|
||||||
|
.addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION))
|
||||||
|
.components(new Components().addSecuritySchemes(HttpHeaders.AUTHORIZATION,new SecurityScheme()
|
||||||
|
.name(HttpHeaders.AUTHORIZATION).type(SecurityScheme.Type.HTTP).scheme("Bearer ")));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,15 @@ package com.gw.test.config;
|
|||||||
|
|
||||||
import com.gw.test.filters.*;
|
import com.gw.test.filters.*;
|
||||||
import com.gw.test.utils.JWTUtil;
|
import com.gw.test.utils.JWTUtil;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SecurityBeanConfig {
|
public class SecurityBeanConfig {
|
||||||
@Bean
|
@Bean
|
||||||
@@ -41,21 +43,26 @@ public class SecurityBeanConfig {
|
|||||||
return new JwtAuthenticationTokenFilter(userDetailsService,jwtTokenUtil);
|
return new JwtAuthenticationTokenFilter(userDetailsService,jwtTokenUtil);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnBean(name = "dynamicSecurityService")
|
// @ConditionalOnBean(name = "dynamicSecurityService")
|
||||||
@Bean
|
@Bean
|
||||||
|
@Autowired
|
||||||
public DynamicAccessDecisionManager dynamicAccessDecisionManager() {
|
public DynamicAccessDecisionManager dynamicAccessDecisionManager() {
|
||||||
return new DynamicAccessDecisionManager();
|
return new DynamicAccessDecisionManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnBean(name = "dynamicSecurityService")
|
// @ConditionalOnBean(name = "dynamicSecurityService")
|
||||||
@Bean
|
@Bean
|
||||||
|
// @Lazy
|
||||||
public DynamicSecurityMetadataSource dynamicSecurityMetadataSource(DynamicSecurityService dynamicSecurityService) {
|
public DynamicSecurityMetadataSource dynamicSecurityMetadataSource(DynamicSecurityService dynamicSecurityService) {
|
||||||
|
// log.error("=============={}",dynamicSecurityService.loadDataSource());
|
||||||
return new DynamicSecurityMetadataSource(dynamicSecurityService);
|
return new DynamicSecurityMetadataSource(dynamicSecurityService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnBean(name = "dynamicSecurityService")
|
// @ConditionalOnBean(name = "dynamicSecurityService")
|
||||||
@Bean
|
@Bean
|
||||||
|
// @Lazy
|
||||||
public DynamicSecurityFilter dynamicSecurityFilter(DynamicSecurityMetadataSource dynamicSecurityMetadataSource,IgnoreUrlsConfig ignoreUrlsConfig){
|
public DynamicSecurityFilter dynamicSecurityFilter(DynamicSecurityMetadataSource dynamicSecurityMetadataSource,IgnoreUrlsConfig ignoreUrlsConfig){
|
||||||
|
// log.error("======动态权限注解支持启动========{}",dynamicSecurityMetadataSource);
|
||||||
return new DynamicSecurityFilter(dynamicSecurityMetadataSource,ignoreUrlsConfig);
|
return new DynamicSecurityFilter(dynamicSecurityMetadataSource,ignoreUrlsConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ package com.gw.test.config;
|
|||||||
|
|
||||||
import com.gw.test.filters.*;
|
import com.gw.test.filters.*;
|
||||||
import com.gw.test.utils.JWTUtil;
|
import com.gw.test.utils.JWTUtil;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
@@ -15,8 +13,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
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.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
@@ -26,7 +22,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
private final JWTUtil jwtUtil;
|
// private final JWTUtil jwtUtil;
|
||||||
|
|
||||||
private final IgnoreUrlsConfig ignoreUrlsConfig;
|
private final IgnoreUrlsConfig ignoreUrlsConfig;
|
||||||
|
|
||||||
@@ -36,59 +32,39 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
||||||
|
|
||||||
// @Autowired(required = false)
|
@Autowired(required = false)
|
||||||
// private DynamicSecurityService dynamicSecurityService;
|
private DynamicSecurityService dynamicSecurityService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private DynamicSecurityFilter dynamicSecurityFilter;
|
private DynamicSecurityFilter dynamicSecurityFilter;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
|
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
|
||||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
|
|
||||||
|
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity
|
||||||
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
|
.authorizeRequests();
|
||||||
//不需要保护的资源路径允许访问
|
//不需要保护的资源路径允许访问
|
||||||
for (String url : ignoreUrlsConfig.getUrls()) {
|
for (String url : ignoreUrlsConfig.getUrls()) {
|
||||||
// log.error("[{}] [{}]", "白名单路径", url);
|
log.error("[{}] [{}]", "白名单路径", url);
|
||||||
registry.requestMatchers(url).permitAll();
|
registry.requestMatchers(url).permitAll();
|
||||||
}
|
}
|
||||||
//允许跨域请求的OPTIONS请求
|
//允许跨域请求的OPTIONS请求
|
||||||
registry.requestMatchers(HttpMethod.OPTIONS)
|
registry.requestMatchers(HttpMethod.OPTIONS)
|
||||||
.permitAll();
|
.permitAll();
|
||||||
|
|
||||||
// 任何请求需要身份认证
|
// 任何请求需要身份认证
|
||||||
registry.and()
|
registry.anyRequest()
|
||||||
.authorizeRequests()
|
|
||||||
.anyRequest()
|
|
||||||
.authenticated()
|
.authenticated()
|
||||||
// 关闭跨站请求防护及不使用session
|
// 关闭跨站请求防护及不使用session
|
||||||
.and()
|
.and()
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
|
||||||
.exceptionHandling(exception -> exception
|
.exceptionHandling(exception -> exception
|
||||||
.accessDeniedHandler(restfulAccessDeniedHandler)
|
.accessDeniedHandler(restfulAccessDeniedHandler)
|
||||||
.authenticationEntryPoint(restAuthenticationEntryPoint))
|
.authenticationEntryPoint(restAuthenticationEntryPoint))
|
||||||
// 自定义JWT认证过滤器
|
// 自定义JWT认证过滤器
|
||||||
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
// 添加动态权限校验过滤器
|
.addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
|
||||||
// .addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
|
|
||||||
return httpSecurity.build();
|
return httpSecurity.build();
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// @Bean
|
|
||||||
// public PasswordEncoder passwordEncoder() {
|
|
||||||
// // 密码加密方式
|
|
||||||
// return new BCryptPasswordEncoder();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Bean
|
|
||||||
// public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
|
|
||||||
// .exceptionHandling()
|
|
||||||
// .accessDeniedHandler(restfulAccessDeniedHandler)
|
|
||||||
// .authenticationEntryPoint(restAuthenticationEntryPoint)
|
|
||||||
// // 自定义权限拦截器JWT过滤器
|
|
||||||
// .and()
|
|
||||||
// .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
|
||||||
//有动态权限配置时添加动态权限校验过滤器
|
|
||||||
// if(dynamicSecurityService != null){
|
|
||||||
// registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ package com.gw.test.config;
|
|||||||
import com.gw.test.filters.DynamicSecurityService;
|
import com.gw.test.filters.DynamicSecurityService;
|
||||||
import com.gw.test.service.IGuoWeiService;
|
import com.gw.test.service.IGuoWeiService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.access.SecurityConfig;
|
import org.springframework.security.access.SecurityConfig;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台用户安全配置
|
* 后台用户安全配置
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Configuration
|
@Configuration
|
||||||
public class UserSecurityConfig {
|
public class UserSecurityConfig {
|
||||||
@@ -34,15 +34,17 @@ public class UserSecurityConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DynamicSecurityService dynamicSecurityService() {
|
public DynamicSecurityService dynamicSecurityService() {
|
||||||
|
log.error("========动态权限配置加载========");
|
||||||
return () -> {
|
return () -> {
|
||||||
Map<String, ConfigAttribute> map = new ConcurrentHashMap<>();
|
Map<String, ConfigAttribute> map = new ConcurrentHashMap<>();
|
||||||
Map<String,String> apis = new HashMap<>();
|
Map<String,String> apis = new HashMap<>();
|
||||||
apis.put("查询用户","ROLE_USER");
|
apis.put("/guowei/list","查询所有");
|
||||||
apis.put("新增用户","ROLE_ADMIN");
|
apis.put("/guowei/update","修改");
|
||||||
apis.put("删除用户","ROLE_ADMIN");
|
apis.put("/guowei/delete","删除");
|
||||||
apis.put("修改用户","ROLE_ADMIN");
|
apis.put("/guowei/add","添加");
|
||||||
for (String api : apis.keySet()) {
|
for (String api : apis.keySet()) {
|
||||||
map.put(api,new SecurityConfig(apis.get(api)));
|
// map.put(api,new SecurityConfig(apis.get(api)));
|
||||||
|
map.put(api,new SecurityConfig(api));
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.gw.test.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
|
||||||
|
//@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
@Autowired
|
||||||
|
// LoginInterceptor loginInterceptor;
|
||||||
|
/**
|
||||||
|
* 跨域配置
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")//
|
||||||
|
.allowedOriginPatterns("*")//
|
||||||
|
.allowedMethods("POST", "GET", "OPTIONS")//
|
||||||
|
.maxAge(3600)//
|
||||||
|
.allowCredentials(true);//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
|
||||||
|
// 对所有访问路径,都通过MyInterceptor类型的拦截器进行拦截
|
||||||
|
// registry.addInterceptor(loginInterceptor)//
|
||||||
|
// .addPathPatterns("/**")//
|
||||||
|
// // 放行登陆接口
|
||||||
|
// .excludePathPatterns("/**/login/**")//
|
||||||
|
// .excludePathPatterns("/**/ip/**")
|
||||||
|
// // swagger需要放行的资源
|
||||||
|
// .excludePathPatterns("/favicon.ico")//
|
||||||
|
// .excludePathPatterns("/error")//
|
||||||
|
// .excludePathPatterns("/doc.html")//
|
||||||
|
// .excludePathPatterns("/webjars/**")//
|
||||||
|
// .excludePathPatterns("/swagger/**")//
|
||||||
|
// .excludePathPatterns("/v3/api-docs/**")//
|
||||||
|
// .excludePathPatterns("/swagger-resources/**")//
|
||||||
|
// .excludePathPatterns("/swagger-ui/**")
|
||||||
|
// .excludePathPatterns("/IpCheck/**")//
|
||||||
|
// ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.gw.test.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.gw.test.domain.Result;
|
||||||
|
import com.gw.test.domain.vo.LoginVo;
|
||||||
|
import com.gw.test.entity.GuoWei;
|
||||||
|
import com.gw.test.service.IGuoWeiService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author gw
|
||||||
|
* @since 2024-09-04
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/guowei")
|
||||||
|
@Tag(name = "用户管理",description = "用户管理接口")
|
||||||
|
public class GuoWeiController {
|
||||||
|
|
||||||
|
private final IGuoWeiService service;
|
||||||
|
|
||||||
|
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||||
|
@Operation(summary = "用户列表",description = "用户列表接口",security = { @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) })
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Result<List<GuoWei>> list(){
|
||||||
|
return Result.ok(service.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
// @SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||||
|
// @Operation(summary = "添加用户",description = "添加用户接口")
|
||||||
|
// @PostMapping("/add")
|
||||||
|
// public Result<Void> save(@RequestBody GuoWei guoWei) {
|
||||||
|
// service.save(guoWei);
|
||||||
|
// return Result.ok();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||||
|
@Operation(summary = "删除用户",description = "删除用户接口")
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
public Result<Void> delete(@RequestParam("id") Integer id) {
|
||||||
|
service.removeById(id);
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||||
|
@Operation(summary = "用户修改",description = "用户列修改口")
|
||||||
|
@PostMapping("/update")
|
||||||
|
public Result<Void> update(@RequestBody GuoWei guoWei) {
|
||||||
|
service.updateById(guoWei);
|
||||||
|
return Result.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "用户登录",description = "用户登录接口")
|
||||||
|
@PostMapping("/login")
|
||||||
|
public Result<LoginVo> login(String username, String password) {
|
||||||
|
log.error("========>username:{},password:{}",username,password);
|
||||||
|
LoginVo login = service.login(username, password);
|
||||||
|
if (login != null) return Result.ok(login);
|
||||||
|
return Result.error("用户名或密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "用户注册",description = "用户注册接口")
|
||||||
|
@PostMapping("/register")
|
||||||
|
public Result<Void> register(GuoWei guoWei) {
|
||||||
|
boolean re = service.register(guoWei);
|
||||||
|
if (re)
|
||||||
|
return Result.ok();
|
||||||
|
else
|
||||||
|
return Result.error("注册失败");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.gw.test.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author gw
|
||||||
|
* @since 2024-09-04
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("guo_wei")
|
||||||
|
@Schema($schema = "GuoWei对象",description = "")
|
||||||
|
public class GuoWei implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema($schema = "主键")
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Schema($schema = "用户名")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Schema($schema = "密码")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Schema($schema = "创建时间")
|
||||||
|
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@Schema($schema = "手机号")
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
@Schema($schema = "权限")
|
||||||
|
private String permissions;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,21 +3,23 @@ package com.gw.test.entity;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class User implements UserDetails {
|
public class User implements UserDetails {
|
||||||
private GuoWei entity;
|
private GuoWei entity;
|
||||||
|
|
||||||
private List<GrantedAuthority> authorities;
|
private List<String> authorities;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
return this.authorities;
|
return this.authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gw.test.filters;
|
package com.gw.test.filters;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.AccessDecisionManager;
|
import org.springframework.security.access.AccessDecisionManager;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
@@ -9,11 +10,11 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断用户是否有访问权限
|
* 判断用户是否有访问权限
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class DynamicAccessDecisionManager implements AccessDecisionManager {
|
public class DynamicAccessDecisionManager implements AccessDecisionManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -30,6 +31,7 @@ public class DynamicAccessDecisionManager implements AccessDecisionManager {
|
|||||||
//将访问所需资源或用户拥有资源进行比对
|
//将访问所需资源或用户拥有资源进行比对
|
||||||
String needAuthority = configAttribute.getAttribute();
|
String needAuthority = configAttribute.getAttribute();
|
||||||
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
|
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
|
||||||
|
log.error("needAuthority:{},grantedAuthority:{}", needAuthority, grantedAuthority.getAuthority());
|
||||||
if (needAuthority.trim().equals(grantedAuthority.getAuthority())) {
|
if (needAuthority.trim().equals(grantedAuthority.getAuthority())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.gw.test.filters;
|
package com.gw.test.filters;
|
||||||
|
|
||||||
//import com.gw.security.config.IgnoreUrlsConfig;
|
|
||||||
//import jakarta.servlet.Filter;
|
|
||||||
import com.gw.test.config.IgnoreUrlsConfig;
|
import com.gw.test.config.IgnoreUrlsConfig;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -43,6 +41,7 @@ public class DynamicSecurityFilter extends AbstractSecurityInterceptor implement
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
// log.error("进入动态权限过滤器");
|
||||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||||
FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain);
|
FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain);
|
||||||
//OPTIONS请求直接放行
|
//OPTIONS请求直接放行
|
||||||
@@ -53,8 +52,9 @@ public class DynamicSecurityFilter extends AbstractSecurityInterceptor implement
|
|||||||
//白名单请求直接放行
|
//白名单请求直接放行
|
||||||
PathMatcher pathMatcher = new AntPathMatcher();
|
PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
for (String path : ignoreUrlsConfig.getUrls()) {
|
for (String path : ignoreUrlsConfig.getUrls()) {
|
||||||
log.error("=============>ignor:{},{}",path,request.getRequestURI());
|
// log.error("=============>ignor:{},{}",path,request.getRequestURI());
|
||||||
if(pathMatcher.match(path,request.getRequestURI())){
|
if(pathMatcher.match(path,request.getRequestURI())){
|
||||||
|
log.error("=============>白名单请求直接放行{},{}",request.getRequestURI(),path);
|
||||||
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
|
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ package com.gw.test.filters;
|
|||||||
|
|
||||||
import cn.hutool.core.util.URLUtil;
|
import cn.hutool.core.util.URLUtil;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.Data;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.access.ConfigAttribute;
|
import org.springframework.security.access.ConfigAttribute;
|
||||||
import org.springframework.security.web.FilterInvocation;
|
import org.springframework.security.web.FilterInvocation;
|
||||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||||
@@ -42,7 +40,7 @@ public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMe
|
|||||||
//获取当前访问的路径
|
//获取当前访问的路径
|
||||||
String url = ((FilterInvocation) o).getRequestUrl();
|
String url = ((FilterInvocation) o).getRequestUrl();
|
||||||
String path = URLUtil.getPath(url);
|
String path = URLUtil.getPath(url);
|
||||||
log.error("------DynamicSecurityMetadataSource:请求url:{}",url);
|
// log.error("------DynamicSecurityMetadataSource:请求url:{}",url);
|
||||||
PathMatcher pathMatcher = new AntPathMatcher();
|
PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
//获取访问该路径所需资源
|
//获取访问该路径所需资源
|
||||||
for (String pattern : configAttributeMap.keySet()) {
|
for (String pattern : configAttributeMap.keySet()) {
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
|||||||
protected void doFilterInternal(HttpServletRequest request,
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
FilterChain chain) throws ServletException, IOException {
|
FilterChain chain) throws ServletException, IOException {
|
||||||
|
// log.error("================JWT过滤器执行=================");
|
||||||
|
// log.error(request.getRequestURI());
|
||||||
String authHeader = request.getHeader(this.tokenHeader);
|
String authHeader = request.getHeader(this.tokenHeader);
|
||||||
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
|
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
|
||||||
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
|
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gw.test.mapper;
|
||||||
|
|
||||||
|
import com.gw.test.entity.GuoWei;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author gw
|
||||||
|
* @since 2024-09-04
|
||||||
|
*/
|
||||||
|
//@Mapper
|
||||||
|
public interface GuoWeiMapper extends BaseMapper<GuoWei> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.gw.test.service;
|
||||||
|
|
||||||
|
import com.gw.test.domain.vo.LoginVo;
|
||||||
|
import com.gw.test.entity.GuoWei;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author gw
|
||||||
|
* @since 2024-09-04
|
||||||
|
*/
|
||||||
|
public interface IGuoWeiService extends IService<GuoWei> {
|
||||||
|
|
||||||
|
UserDetails loadUserByUsername(String s);
|
||||||
|
|
||||||
|
LoginVo login(String username, String password);
|
||||||
|
|
||||||
|
boolean register(GuoWei guoWei);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.gw.test.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.gw.test.domain.vo.LoginVo;
|
||||||
|
import com.gw.test.entity.GuoWei;
|
||||||
|
import com.gw.test.entity.User;
|
||||||
|
import com.gw.test.mapper.GuoWeiMapper;
|
||||||
|
import com.gw.test.service.IGuoWeiService;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.gw.test.utils.JWTUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务实现类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author gw
|
||||||
|
* @since 2024-09-04
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Service
|
||||||
|
public class GuoWeiServiceImpl extends ServiceImpl<GuoWeiMapper, GuoWei> implements IGuoWeiService {
|
||||||
|
private final JWTUtil JWTUtil;
|
||||||
|
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String s) {
|
||||||
|
QueryWrapper<GuoWei> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("username", s);
|
||||||
|
List<GuoWei> list = list(wrapper);
|
||||||
|
if (list.isEmpty()) return null;
|
||||||
|
GuoWei guoWei = list.getFirst();
|
||||||
|
return new User(guoWei, Arrays.stream(guoWei.getPermissions().split(",")).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginVo login(String username, String password) {
|
||||||
|
User user = (User) loadUserByUsername(username);
|
||||||
|
if (user == null) return null;
|
||||||
|
|
||||||
|
if (!passwordEncoder.matches(password, user.getPassword())) return null;
|
||||||
|
|
||||||
|
|
||||||
|
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
|
||||||
|
LoginVo re = new LoginVo();
|
||||||
|
|
||||||
|
re.setId(user.getEntity().getId());
|
||||||
|
re.setUsername(user.getUsername());
|
||||||
|
re.setToken(JWTUtil.generateToken(user));
|
||||||
|
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean register(GuoWei guoWei) {
|
||||||
|
Long count = lambdaQuery()
|
||||||
|
.eq(GuoWei::getUsername, guoWei.getUsername())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
if (count > 0) return false;
|
||||||
|
|
||||||
|
guoWei.setPassword(passwordEncoder.encode(guoWei.getPassword()));
|
||||||
|
return save(guoWei);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,10 +47,14 @@ secure:
|
|||||||
ignored:
|
ignored:
|
||||||
urls:
|
urls:
|
||||||
- /webjars/**
|
- /webjars/**
|
||||||
|
- /favicon.ico
|
||||||
|
- /swagger/**
|
||||||
- /swagger-resources/**
|
- /swagger-resources/**
|
||||||
- /v3/**
|
- /docs/**
|
||||||
|
- /error
|
||||||
|
- /v3/api-docs/**
|
||||||
|
- /swagger-ui/**
|
||||||
- /swagger-ui.html
|
- /swagger-ui.html
|
||||||
- /docs
|
|
||||||
- /doc.html
|
- /doc.html
|
||||||
- /guowei/login
|
- /guowei/login
|
||||||
- /guowei/register
|
- /guowei/register
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gw.test.mapper.GuoWeiMapper">
|
||||||
|
|
||||||
|
<!-- 通用查询映射结果 -->
|
||||||
|
<resultMap id="BaseResultMap" type="com.gw.test.entity.GuoWei">
|
||||||
|
<id column="id" property="id" />
|
||||||
|
<result column="username" property="username" />
|
||||||
|
<result column="password" property="password" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="phone_number" property="phoneNumber" />
|
||||||
|
<result column="permissions" property="permissions" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user