支持不同域的前后端分离部署

This commit is contained in:
648540858
2023-03-15 19:05:56 +08:00
parent 95688e400b
commit 5fab97cf7e
23 changed files with 226 additions and 155 deletions

View File

@@ -28,15 +28,6 @@ public class AnonymousAuthenticationEntryPoint implements AuthenticationEntry
String username = jwtUser.getUserName();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
SecurityContextHolder.getContext().setAuthentication(token);
System.out.println(jwt);
// 允许跨域
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", origin != null ? origin : "*");
response.setHeader("Access-Control-Allow-Methods", "PUT,POST, GET,DELETE,OPTIONS");
// 允许自定义请求头token(允许head跨域)
response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
response.setHeader("Content-type", "application/json;charset=UTF-8");
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", ErrorCode.ERROR401.getCode());
jsonObject.put("msg", ErrorCode.ERROR401.getMsg());

View File

@@ -24,15 +24,24 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// 忽略登录请求的token验证
String requestURI = request.getRequestURI();
if (requestURI.equalsIgnoreCase("/api/user/login")) {
chain.doFilter(request, response);
return;
}
String jwt = request.getHeader(JwtUtils.getHeader());
// 这里如果没有jwt继续往后走因为后面还有鉴权管理器等去判断是否拥有身份凭证所以是可以放行的
// 没有jwt相当于匿名访问若有一些接口是需要权限的则不能访问这些接口
if (StringUtils.isBlank(jwt)) {
chain.doFilter(request, response);
return;
jwt = request.getParameter(JwtUtils.getHeader());
if (StringUtils.isBlank(jwt)) {
chain.doFilter(request, response);
return;
}
}
JwtUser jwtUser = JwtUtils.verifyToken(jwt);
String username = jwtUser.getUserName();
// TODO 处理各个状态

View File

@@ -23,7 +23,7 @@ public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
private static final String HEADER = "Access-Token";
private static final String HEADER = "access-token";
private static final String AUDIENCE = "Audience";
private static final long EXPIRED_THRESHOLD = 10 * 60;

View File

@@ -27,16 +27,13 @@ public class SecurityUtils {
public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException {
//使用security框架自带的验证token生成器 也可以自定义。
UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password);
// Authentication authenticate = authenticationManager.authenticate(token);
// SecurityContextHolder.getContext().setAuthentication(authenticate);
//认证 如果失败,这里会自动异常后返回,所以这里不需要判断返回值是否为空,确定是否登录成功
Authentication authenticate = authenticationManager.authenticate(token);
LoginUser user = (LoginUser) authenticate.getPrincipal();
SecurityContextHolder.getContext().setAuthentication(token);
// LoginUser user = (LoginUser) authenticate.getPrincipal();
User user = new User();
user.setUsername(username);
LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
return loginUser;
return user;
}
/**

View File

@@ -18,8 +18,13 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 配置Spring Security
@@ -61,12 +66,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
// @Bean
// JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
// JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
// return jwtAuthenticationFilter;
// }
/**
* 描述: 静态资源放行,这里的放行,是不走 Spring Security 过滤器链
@@ -77,27 +76,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
if (!userSetting.isInterfaceAuthentication()) {
web.ignoring().antMatchers("**");
}else {
ArrayList<String> matchers = new ArrayList<>();
matchers.add("/");
matchers.add("/#/**");
matchers.add("/static/**");
matchers.add("/index.html");
matchers.add("/doc.html");
matchers.add("/webjars/**");
matchers.add("/swagger-resources/**");
matchers.add("/v3/api-docs/**");
matchers.add("/js/**");
matchers.addAll(userSetting.getInterfaceAuthenticationExcludes());
// 可以直接访问的静态数据
web.ignoring()
.antMatchers("/")
.antMatchers("/#/**")
.antMatchers("/static/**")
.antMatchers("/index.html")
.antMatchers("/doc.html") // "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**"
.antMatchers("/webjars/**")
.antMatchers("/swagger-resources/**")
.antMatchers("/v3/api-docs/**")
.antMatchers("/favicon.ico")
.antMatchers("/js/**");
List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes();
for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) {
if (interfaceAuthenticationExclude.split("/").length < 4 ) {
logger.warn("{}不满足两级目录,已忽略", interfaceAuthenticationExclude);
}else {
web.ignoring().antMatchers(interfaceAuthenticationExclude);
}
}
web.ignoring().antMatchers(matchers.toArray(new String[0]));
}
}
@@ -121,7 +112,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().contentTypeOptions().disable()
.and().cors()
.and().cors().configurationSource(configurationSource())
.and().csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
@@ -129,50 +120,36 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 配置拦截规则
.and()
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
.antMatchers("/api/user/login","/index/hook/**").permitAll()
.anyRequest().authenticated()
// 异常处理器
.and()
.exceptionHandling()
.authenticationEntryPoint(anonymousAuthenticationEntryPoint)
// .accessDeniedHandler(jwtAccessDeniedHandler)
// 配置自定义的过滤器
// .and()
// .addFilter(jwtAuthenticationFilter)
// 验证码过滤器放在UsernamePassword过滤器之前
// .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
.and().logout().logoutUrl("/api/user/logout").permitAll()
.logoutSuccessHandler(logoutHandler)
;
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// // 设置允许添加静态文件
// http.headers().contentTypeOptions().disable();
// http.authorizeRequests()
// // 放行接口
// .antMatchers("/api/user/login","/index/hook/**").permitAll()
// // 除上面外的所有请求全部需要鉴权认证
// .anyRequest().authenticated()
// // 禁用session
// .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// // 异常处理(权限拒绝、登录失效等)
// .and().exceptionHandling()
// // 匿名用户访问无权限资源时的异常处理
// .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
// // 登录 允许所有用户
// .and().formLogin()
// // 登录成功处理逻辑 在这里给出JWT
// .successHandler(loginSuccessHandler)
// // 登录失败处理逻辑
// .failureHandler(loginFailureHandler)
// // 登出
// .and().logout().logoutUrl("/api/user/logout").permitAll()
// // 登出成功处理逻辑
// .logoutSuccessHandler(logoutHandler)
// // 配置自定义的过滤器
// .and()
// .addFilter(jwtAuthenticationFilter())
// ;
}
CorsConfigurationSource configurationSource(){
// 配置跨域
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
corsConfiguration.setAllowedMethods(Arrays.asList("*"));
corsConfiguration.setMaxAge(3600L);
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
url.registerCorsConfiguration("/**",corsConfiguration);
return url;
}
/**
* 描述: 密码加密算法 BCrypt 推荐使用
**/