添加接口测试token验证

This commit is contained in:
2024-09-05 20:04:11 +08:00
parent 94d72c5f46
commit d9f709de3d
8 changed files with 157 additions and 29 deletions
@@ -0,0 +1,23 @@
package com.gw.test.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.info.License;
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,17 @@ 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
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.context.annotation.Lazy;
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
@@ -23,6 +27,7 @@ public class SecurityBeanConfig {
@Bean @Bean
public JWTUtil jWTUtil() { public JWTUtil jWTUtil() {
log.error("jwtUtil");
return new JWTUtil(); return new JWTUtil();
} }
@@ -43,19 +48,23 @@ public class SecurityBeanConfig {
@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
@Autowired
public DynamicSecurityMetadataSource dynamicSecurityMetadataSource(DynamicSecurityService dynamicSecurityService) { public DynamicSecurityMetadataSource dynamicSecurityMetadataSource(DynamicSecurityService dynamicSecurityService) {
return new DynamicSecurityMetadataSource(dynamicSecurityService); return new DynamicSecurityMetadataSource(dynamicSecurityService);
} }
@ConditionalOnBean(name = "dynamicSecurityService") @ConditionalOnBean(name = "dynamicSecurityService")
@Bean @Bean
@Lazy(value = false)
public DynamicSecurityFilter dynamicSecurityFilter(DynamicSecurityMetadataSource dynamicSecurityMetadataSource,IgnoreUrlsConfig ignoreUrlsConfig){ public DynamicSecurityFilter dynamicSecurityFilter(DynamicSecurityMetadataSource dynamicSecurityMetadataSource,IgnoreUrlsConfig ignoreUrlsConfig){
log.error("动态权限注解支持启动");
return new DynamicSecurityFilter(dynamicSecurityMetadataSource,ignoreUrlsConfig); return new DynamicSecurityFilter(dynamicSecurityMetadataSource,ignoreUrlsConfig);
} }
} }
@@ -18,6 +18,7 @@ import org.springframework.security.config.http.SessionCreationPolicy;
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;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
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;
@@ -36,38 +37,67 @@ 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.authorizeRequests();
// //不需要保护的资源路径允许访问
// for (String url : ignoreUrlsConfig.getUrls()) {
// log.error("[{}] [{}]", "白名单路径", url);
// registry.requestMatchers(url).permitAll();
// }
// //允许跨域请求的OPTIONS请求
// registry.requestMatchers(HttpMethod.OPTIONS)
// .permitAll();
// // 任何请求需要身份认证
// registry.and()
// .authorizeRequests()
// .anyRequest()
// .authenticated()
// // 关闭跨站请求防护及不使用session
// .and()
// .csrf(AbstractHttpConfigurer::disable)
// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// .exceptionHandling(exception -> exception
// .accessDeniedHandler(restfulAccessDeniedHandler)
// .authenticationEntryPoint(restAuthenticationEntryPoint))
// // 自定义JWT认证过滤器
// .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// // 添加动态权限校验过滤器
//// .addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
// return httpSecurity.build();
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);
// 添加动态权限校验过滤器 // 添加动态权限校验过滤器
// if (dynamicSecurityService != null)
// registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
// .addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class); // .addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
return httpSecurity.build(); return httpSecurity.build();
} }
@@ -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/**")//
// ;
}
}
@@ -6,12 +6,12 @@ import com.gw.test.domain.vo.LoginVo;
import com.gw.test.entity.GuoWei; import com.gw.test.entity.GuoWei;
import com.gw.test.service.IGuoWeiService; import com.gw.test.service.IGuoWeiService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@@ -23,6 +23,7 @@ import java.util.List;
* @author gw * @author gw
* @since 2024-09-04 * @since 2024-09-04
*/ */
@Slf4j
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@RequestMapping("/guowei") @RequestMapping("/guowei")
@@ -31,31 +32,35 @@ public class GuoWeiController {
private final IGuoWeiService service; private final IGuoWeiService service;
@Operation(summary = "用户列表",description = "用户列表接口") @SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@PostMapping("/list") @Operation(summary = "用户列表",description = "用户列表接口",security = { @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) })
@GetMapping("/list")
public Result<List<GuoWei>> list(){ public Result<List<GuoWei>> list(){
return Result.ok(service.list()); return Result.ok(service.list());
} }
@Operation(summary = "添加用户",description = "添加用户接口") // @SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@PostMapping("/save") // @Operation(summary = "添加用户",description = "添加用户接口")
public Result<Void> save(GuoWei guoWei) { // @PostMapping("/add")
service.save(guoWei); // public Result<Void> save(@RequestBody GuoWei guoWei) {
return Result.ok(); // service.save(guoWei);
} // return Result.ok();
// }
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@Operation(summary = "删除用户",description = "删除用户接口") @Operation(summary = "删除用户",description = "删除用户接口")
@PostMapping("/delete") @DeleteMapping("/delete")
public Result<Void> delete(Integer id) { public Result<Void> delete(@RequestParam("id") Integer id) {
service.removeById(id); service.removeById(id);
return Result.ok(); return Result.ok();
} }
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@Operation(summary = "用户修改",description = "用户列修改口") @Operation(summary = "用户修改",description = "用户列修改口")
@PostMapping("/update") @PostMapping("/update")
public Result<Void> update(GuoWei guoWei) { public Result<Void> update(@RequestBody GuoWei guoWei) {
service.updateById(guoWei); service.updateById(guoWei);
return Result.ok(); return Result.ok();
} }
@@ -63,7 +68,10 @@ public class GuoWeiController {
@Operation(summary = "用户登录",description = "用户登录接口") @Operation(summary = "用户登录",description = "用户登录接口")
@PostMapping("/login") @PostMapping("/login")
public Result<LoginVo> login(String username, String password) { public Result<LoginVo> login(String username, String password) {
return Result.ok(service.login(username, 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 = "用户注册接口") @Operation(summary = "用户注册",description = "用户注册接口")
@@ -43,6 +43,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请求直接放行
@@ -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 "
+7 -3
View File
@@ -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