mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
feat:.
This commit is contained in:
parent
c4b2dee1d7
commit
c616af407f
@ -70,7 +70,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
|
||||
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
|
||||
// 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的
|
||||
.reuseRefreshTokens(true);
|
||||
.reuseRefreshTokens(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,39 +1,107 @@
|
||||
package com.youlai.auth.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.*;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.CredentialsContainer;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@Slf4j
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
||||
.and()
|
||||
.authorizeRequests().antMatchers("/oauth/public_key","/oauth/logout").permitAll().anyRequest().authenticated()
|
||||
.and()
|
||||
.csrf().disable();
|
||||
// 登录失败处理handler,返回一段json
|
||||
http
|
||||
.formLogin().failureHandler(
|
||||
(req, resp, e) -> {
|
||||
resp.setContentType("application/json;charset=utf-8");
|
||||
PrintWriter out = resp.getWriter();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("status", 401);
|
||||
if (e instanceof LockedException) {
|
||||
map.put("msg", "账户被锁定,登录失败!");
|
||||
} else if (e instanceof BadCredentialsException) {
|
||||
map.put("msg", "用户名或密码输入错误,登录失败!");
|
||||
} else if (e instanceof DisabledException) {
|
||||
map.put("msg", "账户被禁用,登录失败!");
|
||||
} else if (e instanceof AccountExpiredException) {
|
||||
map.put("msg", "账户过期,登录失败!");
|
||||
} else if (e instanceof CredentialsContainer) {
|
||||
map.put("msg", "密码过期,登录失败");
|
||||
} else {
|
||||
map.put("msg", "登录失败!");
|
||||
}
|
||||
out.write(new ObjectMapper().writeValueAsString(map));
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
)
|
||||
.and()
|
||||
.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
|
||||
.and()
|
||||
.authorizeRequests().antMatchers("/oauth/public_key", "/oauth/logout").permitAll().anyRequest().authenticated()
|
||||
.and()
|
||||
.csrf().disable();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果不配置SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
|
||||
* 如果不配置SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
|
||||
*/
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
AuthenticationFailureHandler authenticationFailureHandler() {
|
||||
return (request, response, e) -> {
|
||||
|
||||
/*
|
||||
if (!user.isEnabled()) {
|
||||
throw new DisabledException("该账户已被禁用!");
|
||||
} else if (!user.isAccountNonLocked()) {
|
||||
throw new LockedException("该账号已被锁定!");
|
||||
} else if (!user.isAccountNonExpired()) {
|
||||
throw new AccountExpiredException("该账号已过期!");
|
||||
} else if (!user.isCredentialsNonExpired()) {
|
||||
throw new CredentialsExpiredException("该账户的登录凭证已过期,请重新登录!");
|
||||
}
|
||||
*/
|
||||
if (e instanceof DisabledException) {
|
||||
log.info(e.getMessage());
|
||||
} else if (e instanceof LockedException) {
|
||||
log.info(e.getMessage());
|
||||
} else if (e instanceof AccountExpiredException) {
|
||||
log.info(e.getMessage());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.youlai.auth.exception;
|
||||
|
||||
import com.youlai.common.core.result.Result;
|
||||
import com.youlai.common.core.result.ResultCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
public class AuthExceptionHandler {
|
||||
|
||||
@ExceptionHandler(InvalidTokenException.class)
|
||||
public Result handleBizException(InvalidTokenException e) {
|
||||
return Result.custom(ResultCode.TOKEN_INVALID_OR_EXPIRED);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>youlai-common</artifactId>
|
||||
<groupId>com.youlai</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>common-database</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -1,32 +0,0 @@
|
||||
package com.youlai.common.database.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import com.youlai.common.database.handler.MetaHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件,自动识别数据库类型 多租户,请参考官网【插件扩展】
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自动填充数据库创建人、创建时间、更新人、更新时间
|
||||
*/
|
||||
@Bean
|
||||
public GlobalConfig globalConfig() {
|
||||
GlobalConfig globalConfig = new GlobalConfig();
|
||||
globalConfig.setMetaObjectHandler(new MetaHandler());
|
||||
return globalConfig;
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.youlai.common.database.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
**/
|
||||
@Component
|
||||
public class MetaHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("gmtCreate", new Date(), metaObject);
|
||||
this.setFieldValByName("gmtModified", new Date(), metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("gmtCreate", new Date(), metaObject);
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.youlai.common.database.config.MybatisPlusConfig
|
@ -22,10 +22,10 @@
|
||||
<version>${youlai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring boot web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.youlai.gateway.config;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.common.core.constant.AuthConstants;
|
||||
@ -21,7 +20,6 @@ import org.springframework.security.config.annotation.web.reactive.EnableWebFlux
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
|
||||
@ -48,15 +46,14 @@ public class ResourceServerConfig {
|
||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||
http.oauth2ResourceServer().jwt()
|
||||
.jwtAuthenticationConverter(jwtAuthenticationConverter());
|
||||
http.oauth2ResourceServer().authenticationEntryPoint(serverAuthenticationEntryPoint());
|
||||
//http.formLogin().authenticationFailureHandler(serverAuthenticationFailureHandler());
|
||||
http.oauth2ResourceServer().authenticationEntryPoint(authenticationEntryPoint());
|
||||
http.authorizeExchange()
|
||||
.pathMatchers(ArrayUtil.toArray(whiteListConfig.getUrls(), String.class)).permitAll()
|
||||
.anyExchange().access(authorizationManager)
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.accessDeniedHandler(accessDeniedHandler()) // 处理未授权
|
||||
.authenticationEntryPoint(serverAuthenticationEntryPoint()) //处理未认证
|
||||
.authenticationEntryPoint(authenticationEntryPoint()) //处理未认证
|
||||
.and().csrf().disable();
|
||||
|
||||
return http.build();
|
||||
@ -87,37 +84,17 @@ public class ResourceServerConfig {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* token无效或者已过期
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
ServerAuthenticationEntryPoint serverAuthenticationEntryPoint() {
|
||||
ServerAuthenticationEntryPoint authenticationEntryPoint() {
|
||||
return (exchange, e) -> {
|
||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
||||
.flatMap(response -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
String body = JSONUtil.toJsonStr(Result.custom(ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
||||
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
|
||||
return response.writeWith(Mono.just(buffer))
|
||||
.doOnError(error -> DataBufferUtils.release(buffer));
|
||||
});
|
||||
|
||||
return mono;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServerAuthenticationFailureHandler serverAuthenticationFailureHandler() {
|
||||
return (exchange, e) -> {
|
||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getExchange().getResponse()))
|
||||
.flatMap(response -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getHeaders().set("Access-Control-Allow-Origin", "*");
|
||||
response.getHeaders().set("Cache-Control", "no-cache");
|
||||
@ -131,6 +108,7 @@ public class ResourceServerConfig {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @link https://blog.csdn.net/qq_24230139/article/details/105091273
|
||||
@ -148,6 +126,4 @@ public class ResourceServerConfig {
|
||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
|
||||
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user