Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a7ad886284 |
|
|
@ -416,7 +416,7 @@ public class AppController {
|
||||||
String telephone = AesCbcUtils.decrypt(loginUser.getTelephone());
|
String telephone = AesCbcUtils.decrypt(loginUser.getTelephone());
|
||||||
loginUser.setTelephone(telephone);
|
loginUser.setTelephone(telephone);
|
||||||
LoginUser listBean= appservice.checkAccountExist(loginUser);
|
LoginUser listBean= appservice.checkAccountExist(loginUser);
|
||||||
if(StringHelper.isEmpty(listBean.getUsername())){
|
/*if(StringHelper.isEmpty(listBean.getUsername())){
|
||||||
res.setResMsg("fail");
|
res.setResMsg("fail");
|
||||||
res.setResMsg("noThisPhone");
|
res.setResMsg("noThisPhone");
|
||||||
}else if(telephone != null && !telephone.equals(jwtToken)){
|
}else if(telephone != null && !telephone.equals(jwtToken)){
|
||||||
|
|
@ -434,6 +434,22 @@ public class AppController {
|
||||||
UserMap.loginUser(UUID, listBean);
|
UserMap.loginUser(UUID, listBean);
|
||||||
res.setResMsg("success");
|
res.setResMsg("success");
|
||||||
res.setObj(token);
|
res.setObj(token);
|
||||||
|
}*/
|
||||||
|
if(StringHelper.isEmpty(listBean.getPhone())){
|
||||||
|
res.setResMsg("fail");
|
||||||
|
res.setResMsg("noThisPhone");
|
||||||
|
}else {
|
||||||
|
loginUser.setId(listBean.getId());
|
||||||
|
loginUser.setIfJob(listBean.getIfJob());
|
||||||
|
loginUser.setSex(listBean.getSex());
|
||||||
|
loginUser.setSpecialJob(listBean.getSpecialJob());
|
||||||
|
loginUser.setIfHigher(listBean.getIfHigher());
|
||||||
|
String token = tokenService.saveTokenNoPassword(loginUser);
|
||||||
|
loginUser.setToken(token);
|
||||||
|
String UUID = loginUser.getToken();
|
||||||
|
UserMap.loginUser(UUID, listBean);
|
||||||
|
res.setResMsg("success");
|
||||||
|
res.setObj(token);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public class AppserviceImpl implements Appservice {
|
||||||
int pm = appserviceDao.appointSave(pmbean);
|
int pm = appserviceDao.appointSave(pmbean);
|
||||||
int mealid = Integer.parseInt(pmbean.getSetMealId());
|
int mealid = Integer.parseInt(pmbean.getSetMealId());
|
||||||
//标准化预约信息套餐内容进行保存
|
//标准化预约信息套餐内容进行保存
|
||||||
int standid = appserviceDao.getstandByid();
|
// int standid = appserviceDao.getstandByid();
|
||||||
//获取体检项目内容
|
//获取体检项目内容
|
||||||
if ("3".equals(pmbean.getSetMealType()) && "35".equals(pmbean.getHospitalId())){
|
if ("3".equals(pmbean.getSetMealType()) && "35".equals(pmbean.getHospitalId())){
|
||||||
teamstatus = 1;
|
teamstatus = 1;
|
||||||
|
|
@ -119,7 +119,7 @@ public class AppserviceImpl implements Appservice {
|
||||||
String hospital = appserviceDao.hospitalNames(pmbean.getHospitalId());
|
String hospital = appserviceDao.hospitalNames(pmbean.getHospitalId());
|
||||||
SendPhoneMsg(phone,name+"您好,您已成功预约:"+pmbean.getPhyAppontTime()+hospital+"的体检,请准时前往。");
|
SendPhoneMsg(phone,name+"您好,您已成功预约:"+pmbean.getPhyAppontTime()+hospital+"的体检,请准时前往。");
|
||||||
}else {
|
}else {
|
||||||
List<PmPhyCombinBean> beaninfo = appserviceDao.getAllpmphyCombin(mealid, standid);
|
List<PmPhyCombinBean> beaninfo = appserviceDao.getAllpmphyCombin(mealid, 0);
|
||||||
for (int i = 0; i < beaninfo.size(); i++) {
|
for (int i = 0; i < beaninfo.size(); i++) {
|
||||||
//保存到体检人员的体检表中,做历史数据的查询
|
//保存到体检人员的体检表中,做历史数据的查询
|
||||||
corrent.setAppontId(pmbean.getId() + "");
|
corrent.setAppontId(pmbean.getId() + "");
|
||||||
|
|
@ -162,7 +162,7 @@ public class AppserviceImpl implements Appservice {
|
||||||
}
|
}
|
||||||
public static void SendPhoneMsg(String phone, String msg){
|
public static void SendPhoneMsg(String phone, String msg){
|
||||||
String url = "http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!";
|
String url = "http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!";
|
||||||
String uri = url+"&mobile="+ phone + "&content=【云南体检预约】" + msg;
|
String uri = url+"&mobile="+ phone + "&content=【博诺思】" + msg;
|
||||||
HttpRequest.post(uri).execute(false).body();
|
HttpRequest.post(uri).execute(false).body();
|
||||||
// try {
|
// try {
|
||||||
// Thread.sleep(5000);
|
// Thread.sleep(5000);
|
||||||
|
|
@ -233,7 +233,7 @@ public class AppserviceImpl implements Appservice {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int code = random.nextInt(9000) + 1000;
|
int code = random.nextInt(9000) + 1000;
|
||||||
String url = "http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!";
|
String url = "http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!";
|
||||||
String uri = url+"&mobile="+ user.getTelephone() + "&content=【云南体检预约】提醒您,您的登录验证码是:"+code ;
|
String uri = url+"&mobile="+ user.getTelephone() + "&content=【博诺思】提醒您,您的登录验证码是:"+code ;
|
||||||
HttpRequest.post(uri).execute(false).body();
|
HttpRequest.post(uri).execute(false).body();
|
||||||
return code+"";
|
return code+"";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* spring security配置
|
* spring security配置
|
||||||
|
|
@ -39,9 +38,6 @@ public class BnsSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenFilter tokenFilter;
|
private TokenFilter tokenFilter;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CorsConfigurationSource corsConfigurationSource;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
|
|
@ -50,7 +46,7 @@ public class BnsSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.csrf().disable();
|
http.csrf().disable();
|
||||||
http.cors(cors -> cors.configurationSource(corsConfigurationSource));
|
|
||||||
// 基于token,所以不需要session
|
// 基于token,所以不需要session
|
||||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||||
|
|
||||||
|
|
@ -64,7 +60,7 @@ public class BnsSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
|
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
|
||||||
http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
||||||
// 解决不允许显示在iframe的问题
|
// 解决不允许显示在iframe的问题
|
||||||
//http.headers().frameOptions().disable();
|
http.headers().frameOptions().disable();
|
||||||
http.headers().cacheControl();
|
http.headers().cacheControl();
|
||||||
|
|
||||||
http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package com.bonus.boot.manager.manager.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跨域配置类
|
|
||||||
* 解决前后端不分离项目的跨域问题
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class CorsConfig implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
@Value("${cors.allowed-origins}")
|
|
||||||
private String allowedOrigins;
|
|
||||||
|
|
||||||
@Value("${cors.allowed-methods}")
|
|
||||||
private String allowedMethods;
|
|
||||||
|
|
||||||
@Value("${cors.allowed-headers}")
|
|
||||||
private String allowedHeaders;
|
|
||||||
|
|
||||||
@Value("${cors.allow-credentials}")
|
|
||||||
private boolean allowCredentials;
|
|
||||||
|
|
||||||
@Value("${cors.max-age}")
|
|
||||||
private long maxAge;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addCorsMappings(CorsRegistry registry) {
|
|
||||||
registry.addMapping("/**")
|
|
||||||
.allowedOriginPatterns(getAllowedOriginPatterns().toArray(new String[0]))
|
|
||||||
.allowedMethods(getAllowedMethodArray())
|
|
||||||
.allowedHeaders(getAllowedHeaderArray())
|
|
||||||
.allowCredentials(allowCredentials)
|
|
||||||
.maxAge(maxAge)
|
|
||||||
.exposedHeaders("Content-Length", "Content-Type", "Token", "Authorization");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public CorsConfigurationSource corsConfigurationSource() {
|
|
||||||
CorsConfiguration configuration = new CorsConfiguration();
|
|
||||||
configuration.setAllowedOriginPatterns(getAllowedOriginPatterns());
|
|
||||||
configuration.setAllowedMethods(Arrays.asList(getAllowedMethodArray()));
|
|
||||||
configuration.setAllowedHeaders(Arrays.asList(getAllowedHeaderArray()));
|
|
||||||
configuration.setExposedHeaders(Arrays.asList("Content-Length", "Content-Type", "Token", "Authorization"));
|
|
||||||
configuration.setAllowCredentials(allowCredentials);
|
|
||||||
configuration.setMaxAge(maxAge);
|
|
||||||
|
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
|
||||||
// 统一仅注册一套白名单策略,避免出现“*”
|
|
||||||
source.registerCorsConfiguration("/**", configuration);
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getAllowedOriginPatterns() {
|
|
||||||
if (allowedOrigins == null || allowedOrigins.trim().isEmpty()) {
|
|
||||||
return Arrays.asList(
|
|
||||||
"http://localhost:*",
|
|
||||||
"http://127.0.0.1:*",
|
|
||||||
"http://192.168.*.*:*",
|
|
||||||
"http://10.*.*.*:*"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Arrays.asList(allowedOrigins.split(","));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getAllowedMethodArray() {
|
|
||||||
if (allowedMethods == null || allowedMethods.trim().isEmpty()) {
|
|
||||||
return new String[]{"GET", "POST", "PUT", "DELETE", "OPTIONS"};
|
|
||||||
}
|
|
||||||
return allowedMethods.split(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getAllowedHeaderArray() {
|
|
||||||
if (allowedHeaders == null || allowedHeaders.trim().isEmpty()) {
|
|
||||||
return new String[]{"Content-Type", "X-Requested-With", "Token", "Authorization", "X-Custom-Header"};
|
|
||||||
}
|
|
||||||
return allowedHeaders.split(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
package com.bonus.boot.manager.manager.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.*;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Order(1) // 确保过滤器优先级
|
|
||||||
public class CspFilter implements Filter {
|
|
||||||
|
|
||||||
// 静态资源扩展名模式
|
|
||||||
private static final Pattern STATIC_RESOURCE_PATTERN = Pattern.compile(
|
|
||||||
".*\\.(css|js|map|png|jpg|jpeg|gif|ico|svg|webp|bmp|" +
|
|
||||||
"woff|woff2|ttf|eot|otf|pdf|txt|xml|json|" +
|
|
||||||
"zip|rar|7z|tar|gz|mp4|mp3|wav|avi|mov|webm|" +
|
|
||||||
"doc|docx|xls|xlsx|ppt|pptx)$",
|
|
||||||
Pattern.CASE_INSENSITIVE
|
|
||||||
);
|
|
||||||
|
|
||||||
// 静态资源路径前缀
|
|
||||||
private static final List<String> STATIC_PATH_PREFIXES = Arrays.asList(
|
|
||||||
"/static/", "/public/", "/resources/", "/assets/", "/css/", "/js/",
|
|
||||||
"/images/", "/img/", "/fonts/", "/webjars/", "/vendor/", "/dist/",
|
|
||||||
"/uploads/", "/downloads/", "/libs/", "/layui/"
|
|
||||||
);
|
|
||||||
|
|
||||||
// WebGL和3D地图相关页面路径
|
|
||||||
private static final List<String> WEBGL_PAGE_PATHS = Arrays.asList(
|
|
||||||
"/pages/synthesisQuery/digitalSignage.html",
|
|
||||||
"/pages/basic/lineManagement/child/setSpanTowerLonAndLat.html"
|
|
||||||
);
|
|
||||||
|
|
||||||
@Value("${spring.profiles.active:prod}")
|
|
||||||
private String activeProfile;
|
|
||||||
|
|
||||||
@Value("${csp.report-only:false}")
|
|
||||||
private boolean cspReportOnly;
|
|
||||||
|
|
||||||
@Value("${csp.allow-iframe:true}")
|
|
||||||
private boolean allowIframe;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response,
|
|
||||||
FilterChain chain) throws IOException, ServletException {
|
|
||||||
|
|
||||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
|
||||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
|
||||||
String requestUri = httpRequest.getRequestURI();
|
|
||||||
|
|
||||||
// 设置所有必要的安全头
|
|
||||||
setSecurityHeaders(httpResponse, requestUri);
|
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSecurityHeaders(HttpServletResponse response, String requestUri) {
|
|
||||||
// 1. 设置ClickJacking防护头(优先解决)
|
|
||||||
setClickJackingProtectionHeaders(response, requestUri);
|
|
||||||
|
|
||||||
// 2. 设置CSP头
|
|
||||||
setCspHeader(response, requestUri);
|
|
||||||
|
|
||||||
// 3. 设置其他安全头
|
|
||||||
setAdditionalSecurityHeaders(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCspHeader(HttpServletResponse response, String requestUri) {
|
|
||||||
String cspPolicy;
|
|
||||||
|
|
||||||
if (isStaticResource(requestUri)) {
|
|
||||||
// 静态资源使用简单策略
|
|
||||||
cspPolicy = "default-src 'self'";
|
|
||||||
}
|
|
||||||
else if (isLoginPage(requestUri)) {
|
|
||||||
// 登录页面 - 使用安全的CSP策略,移除不安全的指令
|
|
||||||
String frameAncestors = allowIframe ? "'self'" : "'none'";
|
|
||||||
|
|
||||||
cspPolicy = "default-src 'self'; " +
|
|
||||||
// 允许同源脚本和外部JavaScript库
|
|
||||||
"script-src 'self' 'unsafe-inline' https:; " +
|
|
||||||
// 只允许同源样式
|
|
||||||
"style-src 'self' 'unsafe-inline' https:; " +
|
|
||||||
// 只允许同源图片和数据URI
|
|
||||||
"img-src 'self' data: blob: https:; " +
|
|
||||||
// 只允许同源字体和数据URI
|
|
||||||
"font-src 'self' data: https:; " +
|
|
||||||
// 只允许同源连接
|
|
||||||
"connect-src 'self' https:; " +
|
|
||||||
"frame-ancestors " + frameAncestors + "; " +
|
|
||||||
"form-action 'self'; " +
|
|
||||||
"object-src 'none'; " +
|
|
||||||
"base-uri 'self'; " +
|
|
||||||
"report-uri /api/csp-violation";
|
|
||||||
}
|
|
||||||
else if (isWebglPage(requestUri)) {
|
|
||||||
// WebGL和3D地图页面 - 需要更宽松的策略支持WebGL、Worker等
|
|
||||||
String frameAncestors = allowIframe ? "'self'" : "'none'";
|
|
||||||
|
|
||||||
cspPolicy = "default-src 'self'; " +
|
|
||||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data:; " +
|
|
||||||
"style-src 'self' 'unsafe-inline' data: blob:; " +
|
|
||||||
"img-src 'self' data: blob: https:; " +
|
|
||||||
"font-src 'self' data: blob: https:; " +
|
|
||||||
"connect-src 'self' https: blob: data: http://data.mars3d.cn; " +
|
|
||||||
"frame-ancestors " + frameAncestors + "; " +
|
|
||||||
"form-action 'self'; " +
|
|
||||||
"object-src 'none'; " +
|
|
||||||
"base-uri 'self'; " +
|
|
||||||
"worker-src 'self' blob: data:; " +
|
|
||||||
"child-src 'self' blob: data:; " +
|
|
||||||
"report-uri /api/csp-violation"; // 移除 upgrade-insecure-requests,避免强制HTTPS
|
|
||||||
} else {
|
|
||||||
// 普通HTML页面 - 根据配置决定是否允许iframe
|
|
||||||
String frameAncestors = allowIframe ? "'self'" : "'none'";
|
|
||||||
|
|
||||||
cspPolicy = "default-src 'self'; " +
|
|
||||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; " +
|
|
||||||
"style-src 'self' 'unsafe-inline' https:; " +
|
|
||||||
"img-src 'self' data: blob: https:; " +
|
|
||||||
"font-src 'self' data: https:; " +
|
|
||||||
"connect-src 'self' https:; " +
|
|
||||||
"frame-ancestors " + frameAncestors + "; " +
|
|
||||||
"form-action 'self'; " +
|
|
||||||
"object-src 'none'; " +
|
|
||||||
"base-uri 'self'; " +
|
|
||||||
"report-uri /api/csp-violation"; // 移除 upgrade-insecure-requests,避免强制HTTPS
|
|
||||||
}
|
|
||||||
|
|
||||||
String headerName = cspReportOnly ?
|
|
||||||
"Content-Security-Policy-Report-Only" : "Content-Security-Policy";
|
|
||||||
|
|
||||||
response.setHeader(headerName, cspPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setClickJackingProtectionHeaders(HttpServletResponse response, String requestUri) {
|
|
||||||
// 对于静态资源,使用宽松的ClickJacking防护
|
|
||||||
if (isStaticResource(requestUri)) {
|
|
||||||
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于HTML页面,根据配置决定防护级别
|
|
||||||
if (allowIframe) {
|
|
||||||
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
|
||||||
} else {
|
|
||||||
response.setHeader("X-Frame-Options", "DENY");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAdditionalSecurityHeaders(HttpServletResponse response) {
|
|
||||||
response.setHeader("X-Content-Type-Options", "nosniff");
|
|
||||||
response.setHeader("X-XSS-Protection", "1; mode=block");
|
|
||||||
response.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
||||||
response.setHeader("Permissions-Policy",
|
|
||||||
"geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=()");
|
|
||||||
|
|
||||||
// 注意:HSTS 只应在 HTTPS 部署下开启;当前未在此处强制设置
|
|
||||||
// 如需开启,请在 HTTPS 部署完成后,通过配置控制
|
|
||||||
// 例如:Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isStaticResource(String uri) {
|
|
||||||
if (uri == null || uri.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String path = uri.split("\\?")[0];
|
|
||||||
|
|
||||||
if (STATIC_RESOURCE_PATTERN.matcher(path).matches()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATIC_PATH_PREFIXES.stream().anyMatch(path::startsWith);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断是否为登录页面
|
|
||||||
*/
|
|
||||||
private boolean isLoginPage(String requestUri) {
|
|
||||||
return requestUri != null && (
|
|
||||||
requestUri.endsWith("/login.html") ||
|
|
||||||
requestUri.endsWith("/login") ||
|
|
||||||
requestUri.contains("/login")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成随机nonce值
|
|
||||||
*/
|
|
||||||
private String generateNonce() {
|
|
||||||
byte[] nonceBytes = new byte[16];
|
|
||||||
new java.util.Random().nextBytes(nonceBytes);
|
|
||||||
return java.util.Base64.getEncoder().encodeToString(nonceBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成内容的SHA-256哈希值
|
|
||||||
*/
|
|
||||||
private String generateHash(String content) {
|
|
||||||
try {
|
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
|
||||||
byte[] hash = digest.digest(content.getBytes("UTF-8"));
|
|
||||||
return "'sha256-" + java.util.Base64.getEncoder().encodeToString(hash) + "'";
|
|
||||||
} catch (Exception e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWebglPage(String uri) {
|
|
||||||
if (uri == null || uri.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String path = uri.split("\\?")[0];
|
|
||||||
return WEBGL_PAGE_PATHS.stream().anyMatch(path::contains);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isProduction() {
|
|
||||||
return "prod".equals(activeProfile) || "production".equals(activeProfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
// 清理资源
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package com.bonus.boot.manager.manager.config;
|
|
||||||
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.*;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 额外的安全头过滤器
|
|
||||||
* 用于设置更多的安全相关头信息
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@Order(2)
|
|
||||||
public class SecurityHeadersFilter implements Filter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response,
|
|
||||||
FilterChain chain) throws IOException, ServletException {
|
|
||||||
|
|
||||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
|
||||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
|
||||||
|
|
||||||
// 设置额外的安全头
|
|
||||||
setAdditionalSecurityHeaders(httpRequest, httpResponse);
|
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAdditionalSecurityHeaders(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
// 1) 缓存控制
|
|
||||||
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
|
|
||||||
response.setHeader("Pragma", "no-cache");
|
|
||||||
response.setHeader("Expires", "0");
|
|
||||||
|
|
||||||
// 2) IE下载策略
|
|
||||||
response.setHeader("X-Download-Options", "noopen");
|
|
||||||
|
|
||||||
// 3) 跨域策略(条件化设置)
|
|
||||||
if (isPotentiallyTrustworthy(request)) {
|
|
||||||
response.setHeader("Cross-Origin-Opener-Policy", "same-origin");
|
|
||||||
response.setHeader("Cross-Origin-Resource-Policy", "same-origin");
|
|
||||||
response.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
|
|
||||||
} else {
|
|
||||||
response.setHeader("Cross-Origin-Opener-Policy", "");
|
|
||||||
response.setHeader("Cross-Origin-Resource-Policy", "");
|
|
||||||
response.setHeader("Cross-Origin-Embedder-Policy", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4) 不再设置已废弃的 Feature-Policy,避免与 Permissions-Policy 冲突
|
|
||||||
// Permissions-Policy 已在 CspFilter 中统一设置
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isPotentiallyTrustworthy(HttpServletRequest request) {
|
|
||||||
boolean isSecure = request.isSecure();
|
|
||||||
String forwardedProto = request.getHeader("X-Forwarded-Proto");
|
|
||||||
if (!isSecure && forwardedProto != null) {
|
|
||||||
isSecure = "https".equalsIgnoreCase(forwardedProto);
|
|
||||||
}
|
|
||||||
String host = request.getServerName();
|
|
||||||
boolean isLocalhost = "localhost".equalsIgnoreCase(host) || "127.0.0.1".equals(host);
|
|
||||||
return isSecure || isLocalhost;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
// 清理资源
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,10 +15,10 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跨域支持
|
* 跨域支持
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
/*@Bean
|
@Bean
|
||||||
public WebMvcConfigurer corsConfigurer() {
|
public WebMvcConfigurer corsConfigurer() {
|
||||||
return new WebMvcConfigurer() {
|
return new WebMvcConfigurer() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -26,11 +26,11 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
registry.addMapping("/**").allowedMethods("*");
|
registry.addMapping("/**").allowedMethods("*");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* datatable分页解析
|
* datatable分页解析
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@ spring.datasource.url=jdbc:mysql://192.168.1.8:23342/yn_tj_appoint?useUnicode=tr
|
||||||
spring.datasource.username=root
|
spring.datasource.username=root
|
||||||
spring.datasource.password=Bonus@yntj123!
|
spring.datasource.password=Bonus@yntj123!
|
||||||
#\u6D4B\u8BD5\u5E93
|
#\u6D4B\u8BD5\u5E93
|
||||||
#spring.datasource.url=jdbc:mysql://192.168.0.14:1115/yn_tj_appoint?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
#spring.datasource.url=jdbc:mysql://192.168.0.14:4418/yn_tj_appoint?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
|
||||||
#spring.datasource.username=root
|
#spring.datasource.username=root
|
||||||
#spring.datasource.password=xbzadmin@szedu14!
|
#spring.datasource.password=Bonus@admin123!
|
||||||
#\u672C\u5730\u5E93
|
#\u672C\u5730\u5E93
|
||||||
#spring.datasource.url=jdbc:mysql://192.168.0.14:1115/yn_tj_appoint?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
#spring.datasource.url=jdbc:mysql://localhost:13306/yn_tj_appoint?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
|
||||||
#spring.datasource.username=root
|
#spring.datasource.username=lSun
|
||||||
#spring.datasource.password=xbzadmin@szedu14!
|
#spring.datasource.password=liang971108@Sun
|
||||||
|
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
spring.datasource.max-idle=10
|
spring.datasource.max-idle=10
|
||||||
|
|
@ -39,12 +39,12 @@ spring.redis.port=23347
|
||||||
spring.redis.password=Bonus@yntj123!
|
spring.redis.password=Bonus@yntj123!
|
||||||
#\u6D4B\u8BD5
|
#\u6D4B\u8BD5
|
||||||
#spring.redis.host=192.168.0.14
|
#spring.redis.host=192.168.0.14
|
||||||
#spring.redis.port=2001
|
#spring.redis.port=2004
|
||||||
#spring.redis.password=Dszbns@Redis123!
|
#spring.redis.password=Plzbns@Redis123!
|
||||||
#\u672C\u5730
|
#\u672C\u5730
|
||||||
#spring.redis.host=127.0.0.1
|
#spring.redis.host=127.0.0.1
|
||||||
#spring.redis.port=6379
|
#spring.redis.port=6379
|
||||||
#spring.redis.password=
|
#spring.redis.password=liang971108lu@L
|
||||||
# \u65E5\u5FD7
|
# \u65E5\u5FD7
|
||||||
logging.config=classpath:logback-boot.xml
|
logging.config=classpath:logback-boot.xml
|
||||||
log.level.root=info
|
log.level.root=info
|
||||||
|
|
@ -62,57 +62,4 @@ spring.http.multipart.maxRequestSize=10Mb
|
||||||
#spring.security.user.password=123
|
#spring.security.user.password=123
|
||||||
token.expire.seconds=7200
|
token.expire.seconds=7200
|
||||||
#\uFFFD\u013C\uFFFD\uFFFD\u03F4\uFFFD
|
#\uFFFD\u013C\uFFFD\uFFFD\u03F4\uFFFD
|
||||||
spring.servlet.multipart.enabled=true
|
spring.servlet.multipart.enabled=true
|
||||||
|
|
||||||
# CSP??????
|
|
||||||
# ????CSP?????true?????false??????
|
|
||||||
csp.report-only=false
|
|
||||||
|
|
||||||
# ???????iframe????true?????iframe?false??????
|
|
||||||
csp.allow-iframe=true
|
|
||||||
|
|
||||||
# ????WebGL???true????false????
|
|
||||||
csp.enable-webgl=true
|
|
||||||
|
|
||||||
# ????? Actuator ????? HTTP ? JMX?
|
|
||||||
management.endpoints.web.exposure.include=""
|
|
||||||
management.endpoints.jmx.exposure.include=""
|
|
||||||
|
|
||||||
# ????????????Spring Boot 2.2+ ???
|
|
||||||
management.endpoint.health.enabled=false
|
|
||||||
management.endpoint.info.enabled=false
|
|
||||||
# ???????? env?beans ?????????
|
|
||||||
management.endpoint.env.enabled=false
|
|
||||||
management.endpoint.beans.enabled=false
|
|
||||||
management.endpoint.configprops.enabled=false
|
|
||||||
management.endpoint.metrics.enabled=false
|
|
||||||
management.endpoint.mappings.enabled=false
|
|
||||||
management.endpoint.caches.enabled=false
|
|
||||||
|
|
||||||
# ????
|
|
||||||
# ?????????????
|
|
||||||
cors.allowed-origins=http://localhost:1616,http://127.0.0.1:1616,http://192.168.0.39:1616,http://192.168.0.14:1616,http://112.29.103.165:1616
|
|
||||||
|
|
||||||
# ???HTTP??
|
|
||||||
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
|
||||||
|
|
||||||
# ??????
|
|
||||||
cors.allowed-headers=Content-Type,X-Requested-With,Token,Authorization,X-Custom-Header
|
|
||||||
|
|
||||||
# ??????????
|
|
||||||
cors.allow-credentials=true
|
|
||||||
|
|
||||||
# ???????????
|
|
||||||
cors.max-age=3600
|
|
||||||
|
|
||||||
# ?????
|
|
||||||
# ??????????
|
|
||||||
security.headers.strict=true
|
|
||||||
|
|
||||||
# ????HSTS?HTTP???????
|
|
||||||
security.hsts.enabled=true
|
|
||||||
|
|
||||||
# ??????????
|
|
||||||
security.headers.clear-server-info=true
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
FROM
|
FROM
|
||||||
pm_base_physical pbp
|
pm_base_physical pbp
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
pm_phy_organization ppo ON ppo.id = pbp.depart_id
|
pm_organization ppo ON ppo.id = pbp.depart_id
|
||||||
where
|
where
|
||||||
pbp.id=#{id} and pbp.is_active='1'
|
pbp.id=#{id} and pbp.is_active='1'
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -375,18 +375,14 @@
|
||||||
</select>
|
</select>
|
||||||
<select id="getPhysicalExamination" resultType="com.bonus.boot.manager.app.beans.HospitalBean">
|
<select id="getPhysicalExamination" resultType="com.bonus.boot.manager.app.beans.HospitalBean">
|
||||||
SELECT
|
SELECT
|
||||||
set_meal as id,
|
pbp.base_name_id as id,
|
||||||
case set_meal
|
pn.type_name as text
|
||||||
when '1' then '心血管'
|
|
||||||
when '2' then '肿瘤'
|
|
||||||
when '3' then '综合'
|
|
||||||
else ''
|
|
||||||
end as text
|
|
||||||
FROM
|
FROM
|
||||||
pm_base_physical
|
pm_base_physical pbp
|
||||||
|
LEFT JOIN pm_base_type_package_name pn ON pbp.base_name_id = pn.id
|
||||||
WHERE
|
WHERE
|
||||||
idcard = #{idcard}
|
pbp.idcard = #{idcard}
|
||||||
AND is_active = '1'
|
AND pbp.is_active = '1'
|
||||||
</select>
|
</select>
|
||||||
<select id="getCareerHospital" resultType="com.bonus.boot.manager.app.beans.HospitalBean">
|
<select id="getCareerHospital" resultType="com.bonus.boot.manager.app.beans.HospitalBean">
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
1.主分支
|
1.notMerge分支用于修改体检名称-施亮提出
|
||||||
|
2.不能与主分支master合并
|
||||||
|
3.更新日期 2025-06-30
|
||||||
Loading…
Reference in New Issue