支持不同域的前后端分离部署
This commit is contained in:
@@ -14,7 +14,8 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -48,13 +49,6 @@ public class ApiAccessFilter extends OncePerRequestFilter {
|
||||
long start = System.currentTimeMillis(); // 请求进入时间
|
||||
String uriName = ApiSaveConstant.getVal(servletRequest.getRequestURI());
|
||||
|
||||
String origin = servletRequest.getHeader("Origin");
|
||||
servletResponse.setContentType("application/json;charset=UTF-8");
|
||||
servletResponse.setHeader("Access-Control-Allow-Origin", origin != null ? origin : "*");
|
||||
servletResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
servletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
|
||||
servletResponse.setHeader("Access-Control-Max-Age", "3600");
|
||||
servletResponse.setHeader("Access-Control-Allow-Headers", "token,Content-Type,Content-Length, Authorization, Accept,X-Requested-With,domain,zdy");
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
|
||||
if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) {
|
||||
|
||||
@@ -32,6 +32,17 @@ public class GlobalExceptionHandler {
|
||||
return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认异常处理
|
||||
* @param e 异常
|
||||
* @return 统一返回结果
|
||||
*/
|
||||
@ExceptionHandler(IllegalStateException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public WVPResult<String> exceptionHandler(IllegalStateException e) {
|
||||
return WVPResult.fail(ErrorCode.ERROR400);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自定义异常处理, 处理controller中返回的错误
|
||||
|
||||
@@ -55,6 +55,8 @@ public class UserSetting {
|
||||
|
||||
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
|
||||
|
||||
private List<String> allowedOrigins = new ArrayList<>();
|
||||
|
||||
public Boolean getSavePositionHistory() {
|
||||
return savePositionHistory;
|
||||
}
|
||||
@@ -218,4 +220,12 @@ public class UserSetting {
|
||||
public void setSipLog(Boolean sipLog) {
|
||||
this.sipLog = sipLog;
|
||||
}
|
||||
|
||||
public List<String> getAllowedOrigins() {
|
||||
return allowedOrigins;
|
||||
}
|
||||
|
||||
public void setAllowedOrigins(List<String> allowedOrigins) {
|
||||
this.allowedOrigins = allowedOrigins;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 处理各个状态
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 推荐使用
|
||||
**/
|
||||
|
||||
@@ -28,6 +28,10 @@ public class WVPResult<T> implements Cloneable{
|
||||
return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t);
|
||||
}
|
||||
|
||||
public static WVPResult success() {
|
||||
return new WVPResult<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}
|
||||
|
||||
public static <T> WVPResult<T> success(T t) {
|
||||
return success(t, ErrorCode.SUCCESS.getMsg());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import java.text.ParseException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "国标设备配置")
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/device/config")
|
||||
public class DeviceConfig {
|
||||
|
||||
@@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.apache.ibatis.annotations.Options;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -97,8 +98,10 @@ public class DeviceQuery {
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@GetMapping("/devices")
|
||||
@Options()
|
||||
public PageInfo<Device> devices(int page, int count){
|
||||
|
||||
// if (page == null) page = 0;
|
||||
// if (count == null) count = 20;
|
||||
return storager.queryVideoDeviceList(page, count,null);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -70,9 +69,6 @@ public class ServerController {
|
||||
private int serverPort;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "用户管理")
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
public class UserController {
|
||||
@@ -47,7 +46,7 @@ public class UserController {
|
||||
@Parameter(name = "username", description = "用户名", required = true)
|
||||
@Parameter(name = "password", description = "密码(32位md5加密)", required = true)
|
||||
public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){
|
||||
LoginUser user = null;
|
||||
LoginUser user;
|
||||
try {
|
||||
user = SecurityUtils.login(username, password, authenticationManager);
|
||||
} catch (AuthenticationException e) {
|
||||
@@ -62,6 +61,25 @@ public class UserController {
|
||||
return user;
|
||||
}
|
||||
|
||||
// @GetMapping("/logout")
|
||||
// @PostMapping("/logout")
|
||||
// @Operation(summary = "登出")
|
||||
// public LoginUser logout(){
|
||||
// LoginUser user;
|
||||
// try {
|
||||
// user = SecurityUtils.login(username, password, authenticationManager);
|
||||
// } catch (AuthenticationException e) {
|
||||
// throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
// }
|
||||
// if (user == null) {
|
||||
// throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误");
|
||||
// }else {
|
||||
// String jwt = JwtUtils.createToken(username, password);
|
||||
// response.setHeader(JwtUtils.getHeader(), jwt);
|
||||
// }
|
||||
// return user;
|
||||
// }
|
||||
|
||||
@PostMapping("/changePassword")
|
||||
@Operation(summary = "修改密码")
|
||||
@Parameter(name = "username", description = "用户名", required = true)
|
||||
|
||||
Reference in New Issue
Block a user