feat(新增): 🚀 整合springSecurity

This commit is contained in:
bunny 2024-04-24 16:22:46 +08:00
parent 2621e03020
commit cc6212a050
12 changed files with 410 additions and 49 deletions

View File

@ -46,5 +46,22 @@
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redisson 分布式锁-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>3.2.4</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,99 @@
package com.atguigu.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
@Slf4j
public class RedisConfiguration {
/**
* 使用StringRedisSerializer序列化为字符串
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
log.info("RedisConfiguration===>使用StringRedisSerializer序列化为字符串");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
// 设置key序列化为string
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置value序列化为JSON使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
/**
* 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
*/
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
log.info("RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题");
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer()))
.entryTtl(Duration.ofDays(365));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config).build();
return cacheManager;
}
/**
* 指定的日期模式
*/
public Jackson2JsonRedisSerializer<Object> jsonRedisSerializer() {
log.info("RedisConfiguration===>指定的日期模式");
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
// 设置ObjectMapper访问权限
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 记录序列化之后的数据类型方便反序列化
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
// LocalDatetime序列化默认不兼容jdk8日期序列化
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// 关闭默认的日期格式化方式默认UTC日期格式 yyyy-MM-ddTHH:mm:ss.SSS
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(timeModule);
serializer.setObjectMapper(mapper);
return serializer;
}
}

View File

@ -31,7 +31,22 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redisson 分布式锁-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>3.2.4</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,78 @@
package com.atguigu.security.config;
import com.atguigu.security.custom.CustomMd5PasswordEncoder;
import com.atguigu.security.filter.TokenAuthenticationFilter;
import com.atguigu.security.filter.TokenLoginFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity //@EnableWebSecurity是开启SpringSecurity的默认行为
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private CustomMd5PasswordEncoder customMd5PasswordEncoder;
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 这是配置的关键决定哪些接口开启防护哪些接口绕过防护
http
// 关闭csrf跨站请求伪造
.csrf().disable()
// 开启跨域以便前端调用接口
.cors().and()
.authorizeRequests()
// 指定某些接口不需要通过验证即可访问登陆接口肯定是不需要认证的
//.antMatchers("/admin/system/index/login").permitAll()
// 这里意思是其它所有接口需要认证才能访问
.anyRequest().authenticated()
.and()
// TokenAuthenticationFilter放到UsernamePasswordAuthenticationFilter的前面这样做就是为了除了登录的时候去查询数据库外其他时候都用token进行认证
.addFilterBefore(new TokenAuthenticationFilter(redisTemplate),
UsernamePasswordAuthenticationFilter.class)
.addFilter(new TokenLoginFilter(authenticationManager(), redisTemplate));
// 禁用session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 指定UserDetailService和加密器
auth.userDetailsService(userDetailsService).passwordEncoder(customMd5PasswordEncoder);
}
/**
* 配置哪些请求不拦截
* 排除swagger相关请求
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/admin/modeler/**", "/diagram-viewer/**", "/editor-app/**", "/*.html",
"/admin/processImage/**",
"/admin/wechat/authorize", "/admin/wechat/userInfo", "/admin/wechat/bindPhone",
"/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html");
}
}

View File

@ -13,4 +13,4 @@ public class CustomMd5PasswordEncoder implements PasswordEncoder {
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()));
}
}
}

View File

@ -1,12 +1,17 @@
package com.atguigu.security.custom;
import com.atguigu.model.system.SysUser;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
@Setter
@Getter
public class CustomUser extends User {
/**
* 我们自己的用户实体对象要调取用户信息时直接获取这个实体对象这里我就不写get/set方法了
*/
@ -17,11 +22,4 @@ public class CustomUser extends User {
this.sysUser = sysUser;
}
public SysUser getSysUser() {
return sysUser;
}
public void setSysUser(SysUser sysUser) {
this.sysUser = sysUser;
}
}
}

View File

@ -0,0 +1,31 @@
package com.atguigu.security.custom;
public class LoginUserInfoHelper {
private static final ThreadLocal<Long> userId = new ThreadLocal<Long>();
private static final ThreadLocal<String> username = new ThreadLocal<String>();
public static Long getUserId() {
return userId.get();
}
public static void setUserId(Long _userId) {
userId.set(_userId);
}
public static void removeUserId() {
userId.remove();
}
public static String getUsername() {
return username.get();
}
public static void setUsername(String _username) {
username.set(_username);
}
public static void removeUsername() {
username.remove();
}
}

View File

@ -2,10 +2,14 @@ package com.atguigu.security.custom;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@Component
public interface UserDetailsService extends org.springframework.security.core.userdetails.UserDetailsService {
public interface UserDetailsService {
/**
* 根据用户名获取用户对象获取不到直接抛异常
*/
@Override
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
}

View File

@ -0,0 +1,81 @@
package com.atguigu.security.filter;
import com.alibaba.fastjson.JSON;
import com.atguigu.common.result.Result;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.common.utlis.JwtHelper;
import com.atguigu.common.utlis.ResponseUtil;
import com.atguigu.security.custom.LoginUserInfoHelper;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final RedisTemplate<String, Object> redisTemplate;
public TokenAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
// 如果是登录接口直接放行
if ("/admin/system/index/login".equals(request.getRequestURI())) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
if (null != authentication) {
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
} else {
ResponseUtil.out(response, Result.build(null, ResultCodeEnum.LOGIN_MOBLE_ERROR));
}
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
// 请求头是否有token
String token = request.getHeader("token");
if (!StringUtils.isEmpty(token)) {
String username = JwtHelper.getUserName(token);
if (!StringUtils.isEmpty(username)) {
// 当前用户信息放到ThreadLocal里面
LoginUserInfoHelper.setUserId(JwtHelper.getUserId(token));
LoginUserInfoHelper.setUsername(username);
// 通过username从redis获取权限数据
String authString = (String) redisTemplate.opsForValue().get(username);
// 把redis获取字符串权限数据转换要求集合类型 List<SimpleGrantedAuthority>
if (!StringUtils.isEmpty(authString)) {
List<Map> maplist = JSON.parseArray(authString, Map.class);
System.out.println(maplist);
List<SimpleGrantedAuthority> authList = new ArrayList<>();
for (Map map : maplist) {
String authority = (String) map.get("authority");
authList.add(new SimpleGrantedAuthority(authority));
}
return new UsernamePasswordAuthenticationToken(username, null, authList);
} else {
return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
}
}
}
return null;
}
}

View File

@ -1,5 +1,6 @@
package com.atguigu.security.fillter;
package com.atguigu.security.filter;
import com.alibaba.fastjson.JSON;
import com.atguigu.common.result.Result;
import com.atguigu.common.result.ResultCodeEnum;
import com.atguigu.common.utlis.JwtHelper;
@ -7,6 +8,7 @@ import com.atguigu.common.utlis.ResponseUtil;
import com.atguigu.security.custom.CustomUser;
import com.atguigu.vo.system.LoginVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -15,67 +17,68 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* 登录过滤器继承UsernamePasswordAuthenticationFilter对用户名密码进行登录校验
* </p>
*/
public class TokenAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
private final RedisTemplate<String, Object> redisTemplate;
// 构造方法
public TokenLoginFilter(AuthenticationManager authenticationManager,
RedisTemplate<String, Object> redisTemplate) {
this.setAuthenticationManager(authenticationManager);
this.setPostOnly(false);
// 指定登录接口及提交方式可以指定任意路径
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/system/index/login", "POST"));
this.redisTemplate = redisTemplate;
}
/**
* 登录认证
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
// 登录认证
// 获取输入的用户名和密码调用方法认证
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response)
throws AuthenticationException {
try {
LoginVo loginVo = new ObjectMapper().readValue(req.getInputStream(), LoginVo.class);
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
// 获取用户信息
LoginVo loginVo = new ObjectMapper().readValue(request.getInputStream(), LoginVo.class);
// 封装对象
Authentication authenticationToken =
new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
// 调用方法
return this.getAuthenticationManager().authenticate(authenticationToken);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 登录成功
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {
// 认证成功调用方法
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication auth) {
// 获取当前用户
CustomUser customUser = (CustomUser) auth.getPrincipal();
String token = JwtHelper.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
// 生成token
String token = JwtHelper.createToken(customUser.getSysUser().getId(),
customUser.getSysUser().getUsername());
// 获取当前用户权限数据放到Redis里面 keyusername value权限数据
redisTemplate.opsForValue().set(customUser.getUsername(),
JSON.toJSONString(customUser.getAuthorities()));
// 返回
Map<String, Object> map = new HashMap<>();
map.put("token", token);
ResponseUtil.out(response, Result.success(map));
}
/**
* 登录失败
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) {
if (e.getCause() instanceof RuntimeException) {
ResponseUtil.out(response, Result.error(null, 204, e.getMessage()));
} else {
ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_MOBLE_ERROR));
}
// 认证失败调用方法
protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException failed) {
ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_MOBLE_ERROR));
}
}
}

View File

@ -405,3 +405,38 @@ Using generated security password: c1b9b421-40ec-420f-88cd-c249c5d26684
14:54:25:578 INFO 16348 --- [http-nio-8800-exec-4] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
14:54:25:583 INFO 16348 --- [http-nio-8800-exec-4] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
16:12:27:427 INFO 16348 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
16:22:14:238 INFO 23040 --- [main] com.atguigu.auth.ServiceAuthApplication : Starting ServiceAuthApplication on Bunny with PID 23040 (F:\java项目\guigu-oa\guigu-oa\service-oa\target\classes started by ACE in F:\java项目\guigu-oa\guigu-oa)
16:22:14:239 INFO 23040 --- [main] com.atguigu.auth.ServiceAuthApplication : The following profiles are active: dev
16:22:14:830 INFO 23040 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
16:22:14:833 INFO 23040 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
16:22:14:855 INFO 23040 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 13ms. Found 0 Redis repository interfaces.
16:22:15:081 INFO 23040 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@3c232051' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:22:15:085 INFO 23040 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:22:15:412 INFO 23040 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8800 (http)
16:22:15:418 INFO 23040 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
16:22:15:418 INFO 23040 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.39]
16:22:15:478 INFO 23040 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
16:22:15:478 INFO 23040 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1206 ms
16:22:15:587 INFO 23040 --- [main] com.atguigu.config.MybatisPlusConfig : 注入MybatisPlus配置类...
16:22:16:085 INFO 23040 --- [main] com.atguigu.config.RedisConfiguration : RedisConfiguration===>使用StringRedisSerializer序列化为字符串
16:22:16:347 INFO 23040 --- [main] com.atguigu.config.RedisConfiguration : RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
16:22:16:351 INFO 23040 --- [main] com.atguigu.config.RedisConfiguration : RedisConfiguration===>指定的日期模式
16:22:16:428 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/admin/modeler/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/diagram-viewer/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/editor-app/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/*.html'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/admin/processImage/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/admin/wechat/authorize'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/admin/wechat/userInfo'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/admin/wechat/bindPhone'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/favicon.ico'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/swagger-resources/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/webjars/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/v2/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/swagger-ui.html/**'], []
16:22:16:429 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/doc.html'], []
16:22:16:495 INFO 23040 --- [main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@39403943, org.springframework.security.web.context.SecurityContextPersistenceFilter@6e7f29d5, org.springframework.security.web.header.HeaderWriterFilter@ff8e36d, org.springframework.web.filter.CorsFilter@1c5fd813, org.springframework.security.web.authentication.logout.LogoutFilter@63ad5fe7, com.atguigu.security.filter.TokenAuthenticationFilter@49338f3, com.atguigu.security.filter.TokenLoginFilter@3c9971af, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7f94541b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@618fb1, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4abdd5e, org.springframework.security.web.session.SessionManagementFilter@4f22fd5d, org.springframework.security.web.access.ExceptionTranslationFilter@94aeba1, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@7adbec34]
16:22:16:531 INFO 23040 --- [main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
16:22:16:712 INFO 23040 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8800 (http) with context path ''
16:22:16:982 INFO 23040 --- [main] com.atguigu.auth.ServiceAuthApplication : Started ServiceAuthApplication in 3.025 seconds (JVM running for 3.551)
16:22:35:146 INFO 23040 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'