
Spring Boot集成XSS过滤器自动化保护Web应用
下载需积分: 50 | 13KB |
更新于2025-09-14
| 164 浏览量 | 举报
收藏
根据提供的文件信息,我们可以生成关于“xss-filter-spring-boot-starter”和Spring Boot中自动XSS过滤的相关知识点。
**Spring Boot自动XSS过滤知识点**
1. **XSS攻击的定义与危害**
XSS攻击,全称为跨站脚本攻击(Cross Site Scripting),是一种常见的网络攻击手段,攻击者在目标网站中注入恶意脚本代码,当其他用户浏览网页时,嵌入的脚本被执行,导致用户信息泄露、网页篡改、会话劫持等安全问题。
2. **XSS攻击的分类**
- 反射型XSS:攻击代码通过用户输入到达网站页面,攻击代码随响应返回到用户浏览器执行。
- 存储型XSS:攻击代码被存储在数据库中,用户访问该页面时,攻击代码被执行。
- DOM型XSS:攻击代码不通过服务器,直接在客户端执行,通常是由于客户端脚本处理不当造成的。
3. **XSS攻击的防御方法**
- 输入验证:对所有输入进行严格的验证,不允许包含HTML代码的输入。
- 输出编码:对输出到HTML页面的数据进行编码,防止恶意脚本执行。
- 内容安全策略(CSP):通过设置HTTP头信息中的Content-Security-Policy指令限制网页加载和执行脚本的策略。
- 使用安全的库:使用经过安全审计的库来处理用户输入和输出。
4. **Spring Boot中的自动XSS过滤**
Spring Boot框架通过集成xss-filter-spring-boot-starter模块,为开发者提供了一个简便的方式来自动实现XSS过滤功能。开发者只需要在项目的pom.xml文件中添加特定的依赖,即可启用自动XSS过滤。
5. **xss-filter-spring-boot-starter模块的使用**
- 依赖添加:在pom.xml文件中添加xss-filter-spring-boot-starter模块的依赖。
```xml
<dependency>
<groupId>com.djk</groupId>
<artifactId>xss-filter-spring-boot-starter</artifactId>
<version>0.0.1</version>
</dependency>
```
- 支持的参数过滤类型:根据文件描述,目前提供了对三种入参类型的XSS过滤支持,不过文件中并未详细说明是哪三种类型。通常这可能包括Controller方法的参数、HTTP请求参数和模板引擎中的变量。
6. **配置与扩展性**
- 通常,自动XSS过滤模块可能会提供配置选项来满足不同的安全需求,比如配置忽略过滤的URL、自定义过滤规则等。
- 开发者可以根据模块的文档进行相关配置,以适应不同的应用场景。
7. **案例分析**
- 文中提供的Controller方法示例没有完全展示,但可以推测是使用@RequestMapping注解的控制器方法。在自动XSS过滤启用后,对于该方法的name参数,如果用户输入包含潜在的XSS攻击代码,系统将自动进行过滤,防止恶意脚本被注入执行。
```java
@RequestMapping("/test1")
public String test1(String name) {
log.error("name:{}", name);
return name;
}
```
- 第二个@RequestMapping注解示例似乎是不完整的,但是可以预见,在启用自动XSS过滤后,对于URL中的参数(如{name, age, tes...}),也会进行XSS攻击的过滤。
8. **版本控制和更新**
- 文件中提到的xss-filter-spring-boot-starter版本为0.0.1,表示这是该项目的起始版本或早期版本。通常,开发者应当关注官方发布的后续版本,以获取最新的安全特性和修复。
9. **最佳实践**
- 建议开发者在开发过程中,持续关注安全问题,并结合使用多种安全措施,比如定期进行安全审计、更新依赖库、进行安全测试,以构建更为安全的Spring Boot应用。
以上是根据给定文件信息总结的关于xss-filter-spring-boot-starter模块在Spring Boot中实现自动XSS过滤的相关知识点。这些内容可以为使用Spring Boot框架进行Web开发的程序员提供重要的安全防护策略和实现方法。
相关推荐















function https(url,data,fu){
$.ajax({
contentType:“application/json”,
url: url, // 假设后端 API 地址
method: “POST”,
data: JSON.stringify(data),
type: “json”,
dataType: “json”,
success:function(e){
console.log(e.data)
if(e.status==200){
console.log(e.data)
fu(e.data)
}else{
alert(e.text)
}
},
error: function (e) {
console.log(e.data)
console.error(e)
alert(“请求失败,请稍后再试!”+e);
}
});
}
function checkLoginStatus() {
if (window.location.href.includes(‘/login.html’)) return;
}
window.addEventListener(‘beforeunload’, function(e) {
console.trace(‘触发页面跳转的堆栈跟踪:’);
});
//安全验证函数
function validateUserSession() {
try {
// 防御性数据获取 + 数据清洗
const rawValue = localStorage.getItem(“name”);
const username = String(rawValue ?? ‘’)
.trim()
.replace(/[\u200B-\u200D\uFEFF]/g, ‘’); // 移除零宽字符
// 调试信息
console.log('[Auth] Raw:', rawValue, 'Processed:', username);
// 复合验证条件
const isValid = (
username.length >= 2 && // 最小长度要求
!/[<>]/.test(username) && // 防止XSS
username !== 'null' &&
username !== 'undefined'
);
if (!isValid) {
console.warn('无效用户标识:', username);
// 安全跳转方法
//window.location.replace('/KuCun2/login.html');
// 立即终止执行
return Promise.reject('Invalid session');
}
// 返回清洗后的用户名
return username;
} catch (error) {
console.error(‘会话验证失败:’, error);
// window.location.replace(‘/KuCun2/login.html’);
return Promise.reject(error);
}
}
function deepMergeArrays(frontend, backend) {
const resultMap = new Map();
// 遍历前端数据并存入 Map 中以便快速查找
frontend.forEach(item => resultMap.set(item.id, { ...item }));
// 遍历后端数据并与前端数据进行合并
backend.forEach(item => {
if (resultMap.has(item.id)) {
// 如果存在相同 ID,则合并两者的内容
resultMap.set(
item.id,
Object.assign(resultMap.get(item.id), item)
);
} else {
// 如果不存在相同 ID,则新增该条目
resultMap.set(item.id, { ...item });
}
});
// 将最终结果转回数组形式
return Array.from(resultMap.values());
}
(function ($){
// 页面加载时检查登录状态
checkLoginStatus();
})(jQuery);
function removeSpecificCharactersAndConvertToNumber(str, charsToRemove) {
const regex = new RegExp([${charsToRemove}], ‘g’); // 创建用于匹配指定字符的正则表达式
const cleanedStr = str.replace(regex, ‘’); // 移除指定字符
const numberValue = parseFloat(cleanedStr); // 转换为浮点数
return isNaN(numberValue) ? null : numberValue; // 如果无法解析,则返回 null
}
<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”>
<modelVersion>4.0.0</modelVersion>
<groupId>KuCun2</groupId>
<artifactId>KuCun2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>KuCun2</name>
<description/>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/>
</parent>
<properties>
<webVersion>4.0</webVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<protobuf.version>3.21.12</protobuf.version>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp.jstl</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.30</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project> package com.kucun;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication(
)
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
//
// ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
// Arrays.stream(ctx.getBeanNamesForType(SecurityFilterChain.class))
// .forEach(System.out::println);
//
//
// // 测试密码加密示例
// BCryptPasswordEncoder encoder = new BCrypt();
// String rawPassword = “987987”;
// String encodedPassword = encoder.encode(rawPassword);
// System.out.println(“加密后的密码:” + encodedPassword);
SpringApplication.run(DemoApplication.class, args);
}
}package com.kucun.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.kucun.Config.Role.RoleConverter;
import com.kucun.Config.user.CustomUserDetails;
import com.kucun.data.entity.User;
import com.kucun.dataDo.UserRepository;
/**
获取数据
@author Administrator
/
@Service
public class CustomUserDetailsService/ implements UserDetailsService /{
//
// @Autowired
// private UserRepository userRepository;
//
// @Autowired
// private RoleConverter roleConverter;
//
// public CustomUserDetailsService() {
//
// super();
// System.out.println(“11111”);
// }
///*
// * 获取数据库中用户信息
// * @param andy 账号
// *
// * @return
// *
// */
// @Override
// public UserDetails loadUserByUsername(String andy) {
// System.out.println(andy);
// User user = userRepository.findByAndy(andy);
// System.out.println(user);
// return new CustomUserDetails(user,
// roleConverter.convert(user.getRole()) // 关键转换点1
// );
// }
}package com.kucun.Config;
// 2. 基础安全配置
//@Configuration
//@EnableWebSecurity // 启用Web安全功能
public class SecurityConfig
//extends WebSecurityConfigurerAdapter
{
// @Override
// public void configure(WebSecurity web) {
// web.ignoring().antMatchers(“/check-session”);
// }
// // 添加自定义Controller
// @RestController
// public static class SessionCheckController {
// @GetMapping(“/check-session”)
// public ResponseEntity<?> checkSession(HttpServletRequest request) {
// return request.getSession(false) != null ?
// ResponseEntity.ok().build() :
// ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
// }
// }
// /**
// * 核心安全过滤器链配置
// * @param http HTTP安全构建器
// * @return 安全过滤器链
// * @throws Exception 配置异常
// *
// * █ 配置逻辑说明:
// * 1. authorizeHttpRequests: 定义访问控制规则
// * 2. formLogin: 配置表单登录
// * 3. logout: 配置注销行为
// * 4. exceptionHandling: 处理权限异常3
// /
//
// // 修正后的配置方法
// @Override
// protected void configure(HttpSecurity http) throws Exception {
//
//
//
// http
// .csrf().disable()
// .sessionManagement()
// .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
// .invalidSessionUrl(“/login.html?session=invalid”)
// .maximumSessions(1)
// .maxSessionsPreventsLogin(false)
// .and()
// .and()
// .addFilterBefore(jsonAuthFilter(), UsernamePasswordAuthenticationFilter.class) // 关键配置
// .authorizeRequests()
// .antMatchers(“/login.html”, “/users/login”).permitAll()
// .antMatchers(“/js/", "/css/”, “/fonts/", "/images/”,“/check-session”,“/main/bootstrap-3.3.7-dist/“).permitAll()
// .antMatchers(”/users/guanli/”).hasAuthority(“ROLE_ADMIN”)
// .anyRequest().authenticated()
// .and()
// .formLogin().disable()
//// .loginPage(“/login.html”)
//// .loginProcessingUrl(“/users/login”)
////
//// .successHandler(ajaxAuthenticationSuccessHandler()) // 自定义成功处理器
//// .failureHandler(ajaxAuthenticationFailureHandler()) // 自定义失败处理器
//// .defaultSuccessUrl(“/index.html”)
//// .failureUrl(“/login.html?error=true”)
//// .usernameParameter(“andy”) // 修改用户名参数名
//// .passwordParameter(“pass”) // 修改密码参数名
//// .and()
//
// .logout()
// .logoutUrl(“/logout”)
// .logoutSuccessUrl(“/login.html”)
// .and()
// .csrf()
// .ignoringAntMatchers(“/users/login”)
// .and()
// .headers()
// .frameOptions().sameOrigin()
// .and()
// .exceptionHandling()
// .accessDeniedHandler(accessDeniedHandler()); // 统一使用Handler
// }
//
//
//
//
//
// // 返回JSON格式的成功响应
// @Bean
// public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() {
// return (request, response, authentication) -> {
//
//
//
// // 强制创建服务端会话
// request.getSession(true);
//
//
//
//
// String contextPath = request.getContextPath();
// HttpSession session = request.getSession(true);
// Cookie cookie = new Cookie(“JSESSIONID”, session.getId());
// cookie.setPath(contextPath.isEmpty() ? “/” : contextPath + “/”);
// cookie.setMaxAge(1800); // 30分钟
// response.addCookie(cookie);
//
//
// //构建安全响应数据
// Map<String, Object> responseData = new HashMap<>();
// responseData.put(“sessionId”, request.getSession().getId());
// responseData.put(“userInfo”,Collections.unmodifiableMap(new HashMap<String, Object>() {/*
// *
// /
// private static final long serialVersionUID = 1L;
//
// {
// put(“Name”, ((CustomUserDetails)authentication.getPrincipal()).getName());
// put(“role”, ((CustomUserDetails)authentication.getPrincipal()).getRole());
// }}));
//
//
//
// // 统一返回JSON格式
// response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// // new ObjectMapper().writeValue(response.getWriter(), responseData);
//
//
//
//
//
//
//
//
//
// response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
//
// response.setStatus(HttpStatus.OK.value());
// System.out.println(authentication.getPrincipal()+“”+authentication.getName());
//
// if (request.getHeader(“X-Requested-With”) == null) { // 非AJAX请求
// response.sendRedirect(“/index.html”);
// } else {
//
// //String re=userDetails.getUser().toString()
// new ObjectMapper().writeValue(response.getWriter(), userDetails.getUser()
// );
//
// }
//
//
//
//
//
//
// };
// }
//
// // 返回401状态码和错误信息
// @Bean
// public AuthenticationFailureHandler ajaxAuthenticationFailureHandler() {
// return (request, response, exception) -> {
// if (request.getHeader(“X-Requested-With”) == null) {
// response.sendRedirect(“/login.html?error=true”);
// } else {
// response.setStatus(HttpStatus.UNAUTHORIZED.value());
// response.getWriter().write(“{"error":"Authentication failed"}”);
// }
// };
// }
//
// // 处理未认证请求
// @Bean
// public AuthenticationEntryPoint ajaxAuthenticationEntryPoint() {
// return (request, response, exception) -> {
// if (request.getHeader(“X-Requested-With”) == null) {
// response.sendRedirect(“/login.html?error=true”);
// } else {
// response.setStatus(HttpStatus.UNAUTHORIZED.value());
// response.getWriter().write(“{"error":"Authentication failed"}”);
// }
// };
// }
//
//
//
//
//
// @Bean
// public JsonUsernamePasswordAuthenticationFilter jsonAuthFilter() throws Exception {
//
// JsonUsernamePasswordAuthenticationFilter filter =
// new JsonUsernamePasswordAuthenticationFilter();
// filter.setAuthenticationManager(authenticationManagerBean());
// filter.setUsernameParameter(“andy”); // 设置自定义参数名
// filter.setPasswordParameter(“pass”);
// filter.setFilterProcessesUrl(“/users/login”);
// filter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler());
// filter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler());
//
// return filter;
// }
//
//
// /*
// * 密码编码器(必须配置)
// * 使用BCrypt强哈希算法加密
// */
// @Bean
// public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// }
//
//
// @Bean
// public AccessDeniedHandler accessDeniedHandler() {
// System.out.println(“0000”);
// return (request, response, ex) -> {
// if (!response.isCommitted()) {
// response.sendRedirect(“/error/403”);
// }
// };
// }
//
//
//}
//
//
//
//
//
//
//class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
// private final ObjectMapper objectMapper = new ObjectMapper();
//
// @Override
// public Authentication attemptAuthentication(HttpServletRequest request,
// HttpServletResponse response)
// throws AuthenticationException {
// System.out.println(“收到认证请求,路径:” + request.getRequestURI());
// System.out.println(“请求方法:” + request.getMethod());
// System.out.println(“Content-Type:” + request.getContentType());
// if (request.getContentType() != null &&
// request.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) {
//
// try (InputStream is = request.getInputStream()) {
// Map<String, String> authMap = objectMapper.readValue(is, Map.class);
//
// String username = authMap.getOrDefault(getUsernameParameter(), “”);
// String password = authMap.getOrDefault(getPasswordParameter(), “”);
//
// // 调试日志
// System.out.println("Authentication attempt with: " + username+‘_’+ password);
//
// UsernamePasswordAuthenticationToken authRequest =
// new UsernamePasswordAuthenticationToken(username, password);
//
// setDetails(request, authRequest);
// return this.getAuthenticationManager().authenticate(authRequest);
// } catch (IOException e) {
// throw new AuthenticationServiceException(“认证请求解析失败”, e);
// }
// }
// Authentication aut= super.attemptAuthentication(request, response);
// System.out.println(“结果:”+aut.isAuthenticated());
//
// return aut;
// }
}
package com.kucun.Config.Role;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.json.Json;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
权限转化
@author Administrator
*/
@Component
public class RoleConverter {
// private static final Map<Integer, String> ROLE_MAP = new HashMap<>();
//
// @PostConstruct
// public void init() {
// ROLE_MAP.put(0, “ROLE_ADMIN”);
// ROLE_MAP.put(1, “ROLE_USER”);
// ROLE_MAP.put(2, “ROLE_MANAGER”);
// ROLE_MAP.put(3, “ROLE_AUDITOR”);
// }
//
// public List<GrantedAuthority> convert(int roleCode) {
// ObjectMapper mapper = new ObjectMapper();
// try {
// System.out.println(mapper.writeValueAsString(Collections.singletonList(
// new SimpleGrantedAuthority(ROLE_MAP.getOrDefault(roleCode, “ROLE_GUEST”)))).toString());//输出[{“authority”:“ROLE_ADMIN”}]
// } catch (JsonProcessingException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// return Collections.singletonList(
// new SimpleGrantedAuthority(ROLE_MAP.getOrDefault(roleCode, “ROLE_GUEST”))
// );
// }
//
}package com.kucun.Config.user;
import java.util.Collection;
import com.kucun.data.entity.User;
public class CustomUserDetails /implements UserDetails/ {
// /**
// *
// */
// private static final long serialVersionUID = 1L;
// private final String andy; // 对应andy字段
// private final String name;
// private final int role;
// private final String password;
// private final User users;
// private final Collection<? extends GrantedAuthority> authorities;
//
// public CustomUserDetails(User user, Collection<? extends GrantedAuthority> authorities) {
// this.andy = user.getAndy();
// this.name = user.getName();
// this.role = user.getRole();
// this.password = user.getPass();
// user.setPass(null);
// this.users=user;
// this.authorities = authorities;
// }
//
// // 实现UserDetails接口方法
// @Override public String getUsername() { return andy; }
// @Override public String getPassword() { return password; }
// @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; }
//
// // 自定义字段访问方法
// public String getName() { return name; }
// public User getUser() { return users; }
// public int getRole() { return role; }
//
// // 其他必要方法
// @Override public boolean isAccountNonExpired() { return true; }
// @Override public boolean isAccountNonLocked() { return true; }
// @Override public boolean isCredentialsNonExpired() { return true; }
// @Override public boolean isEnabled() { return true; }
} <!doctype html>
<html>
<head>
<meta charset=“utf-8”>
<meta name=“viewport” content=“width=device-width, initial-scale=1, maximum-scale=1”>
<title>峤丞板材库存管理</title>
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<link rel=“stylesheet” type=“text/css” href=“fonts/font-awesome-4.7.0/css/font-awesome.min.css”>
<link rel=“stylesheet” type=“text/css” href=“css/util.css”>
<link rel=“stylesheet” type=“text/css” href=“css/main.css”>
<link rel=“stylesheet” type=“text/css” href=“css/index2.css”>
<style type=“text/css”>
*{
margin:0;
padding:0;
}
.frame-header {
height: 60px;
background-color: #23262E;
justify-content: space-between;
}
.frame-header-li{
font-family: Arial, Helvetica, sans-serif;
font-size:40px;
}
.frame-ul{
}
.frame-ul li{
border-style: solid;
border-width:1px 0px 1px 0px;
margin-top: 1px;
height: 35px;
text-align: center
}
#username{
position: absolute;
right: 0; /* 靠右 */
}
.frame-body {
position: fixed;
top: 60px;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: row;
}
.frame-side {
scrollbar-width: none; /* firefox隐藏滚动条 /
-ms-overflow-style: none; / IE 10+隐藏滚动条 /
overflow-x: hidden;
overflow-y: auto;
width: 200px;
background-color:#9e5;
}
.frame-side::-webkit-scrollbar {
display: none; / Chrome Safari 隐藏滚动条*/
}
.frame-main {
flex-grow: 1;
background-color:#fff;
}
.jiaoluo{
margin: auto;
margin-right: 0px;
}
</style>
</head>
<body>
<iframe id="iframeid" name="main" src="main/index.html" width="100%" height="100%" frameborder="0">
</iframe>
</body>
<script type=“text/javascript” src=“js/jquery-3.2.1.min.js”></script>
<script type=“text/javascript” src=“js/jsyilai.js”></script>
</html><!DOCTYPE html>
<html lang=“zh-CN”>
<head>
<title>扁平简洁的登录页面演示_dowebok</title>
<meta charset=“utf-8”>
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<link rel=“stylesheet” type=“text/css” href=“fonts/font-awesome-4.7.0/css/font-awesome.min.css”>
<link rel=“stylesheet” type=“text/css” href=“css/util.css”>
<link rel=“stylesheet” type=“text/css” href=“css/main.css”>
</head>
<body>
登 录
<form class="login100-form validate-form">
用户名
<input class="input100" type="text" name="andy" placeholder="请输入用户名">
密码
<input class="input100" type="password" name="pass" placeholder="请输入用户密码">
<input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me">
<label class="label-checkbox100" for="ckb1">记住我</label>
<button class="login100-form-btn">登 录</button>
</form>
<script type=“text/javascript”>
</script>
<script src=“js/jquery-3.2.1.min.js”></script>
<script type=“text/javascript” src=“js/jsyilai.js”></script>
</body>
</html> yilai.js
(function ($) {
var pathName = window.location.pathname;
console.log(pathName); // 输出类似于 ‘/index.html’
//alert(pathName)
switch (pathName){
case "/KuCun2/login.html":
jQuery.getScript('/KuCun2/js/main.js?'+Date.now())
jQuery.getScript('/KuCun2/js/login.js?'+Date.now())
break;
case "/KuCun2/main/Guanli.html":
jQuery.getScript('/KuCun2/js/main.js?'+Date.now())
jQuery.getScript('/KuCun2/js/guanli.js?'+Date.now())
jQuery.getScript('/KuCun2/main/bootstrap-3.3.7-dist/js/FileSaver.js?'+Date.now())
jQuery.getScript('/KuCun2/main/bootstrap-3.3.7-dist/js/MyTable.js?'+Date.now())
break;
case "/KuCun2/index.html":
jQuery.getScript('/KuCun2/js/main.js?'+Date.now())
jQuery.getScript('/KuCun2/js/index.js?'+Date.now())
break;
}
})(jQuery) main.js
function https(url,data,fu){
$.ajax({
contentType:“application/json”,
url: url, // 假设后端 API 地址
method: “POST”,
data: JSON.stringify(data),
type: “json”,
dataType: “json”,
success:function(e){
console.log(e.data)
if(e.status==200){
console.log(e.data)
fu(e.data)
}else{
alert(e.text)
}
},
error: function (e) {
console.log(e.data)
console.error(e)
alert(“请求失败,请稍后再试!”+e);
}
});
}
function checkLoginStatus() {
if (window.location.href.includes(‘/login.html’)) return;
}
window.addEventListener(‘beforeunload’, function(e) {
console.trace(‘触发页面跳转的堆栈跟踪:’);
});
//安全验证函数
function validateUserSession() {
try {
// 防御性数据获取 + 数据清洗
const rawValue = localStorage.getItem(“name”);
const username = String(rawValue ?? ‘’)
.trim()
.replace(/[\u200B-\u200D\uFEFF]/g, ‘’); // 移除零宽字符
// 调试信息
console.log('[Auth] Raw:', rawValue, 'Processed:', username);
// 复合验证条件
const isValid = (
username.length >= 2 && // 最小长度要求
!/[<>]/.test(username) && // 防止XSS
username !== 'null' &&
username !== 'undefined'
);
if (!isValid) {
console.warn('无效用户标识:', username);
// 安全跳转方法
//window.location.replace('/KuCun2/login.html');
// 立即终止执行
return Promise.reject('Invalid session');
}
// 返回清洗后的用户名
return username;
} catch (error) {
console.error(‘会话验证失败:’, error);
// window.location.replace(‘/KuCun2/login.html’);
return Promise.reject(error);
}
}
function deepMergeArrays(frontend, backend) {
const resultMap = new Map();
// 遍历前端数据并存入 Map 中以便快速查找
frontend.forEach(item => resultMap.set(item.id, { ...item }));
// 遍历后端数据并与前端数据进行合并
backend.forEach(item => {
if (resultMap.has(item.id)) {
// 如果存在相同 ID,则合并两者的内容
resultMap.set(
item.id,
Object.assign(resultMap.get(item.id), item)
);
} else {
// 如果不存在相同 ID,则新增该条目
resultMap.set(item.id, { ...item });
}
});
// 将最终结果转回数组形式
return Array.from(resultMap.values());
}
(function ($){
// 页面加载时检查登录状态
checkLoginStatus();
})(jQuery);
function removeSpecificCharactersAndConvertToNumber(str, charsToRemove) {
const regex = new RegExp([${charsToRemove}], ‘g’); // 创建用于匹配指定字符的正则表达式
const cleanedStr = str.replace(regex, ‘’); // 移除指定字符
const numberValue = parseFloat(cleanedStr); // 转换为浮点数
return isNaN(numberValue) ? null : numberValue; // 如果无法解析,则返回 null
}
logi.js/// <reference path=“jquery.d.ts” />
// ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …function(){
// (“#submit”).click(function(){
//
//
// ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …
// andy:(“#andy”).val(),
// pass:ParseError: KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲pass").val(),
/…(“#name”).val()}),
// type:“post”,
// contentType:“application/json”,
// success:function(e){
// alert(e)
// }
// });
//
//
// });
// })
(function ($) {
“use strict”;
/*==================================================================
[ Focus Contact2 ]*/
$('.input100').each(function () {
$(this).on('blur', function () {
if ($(this).val().trim() != "") {
$(this).addClass('has-val');
} else {
$(this).removeClass('has-val');
}
})
})
/*==================================================================
[ Validate ]*/
var input = $('.validate-input .input100');
$('.validate-form').on('submit', function (e) {
e.preventDefault();
var check = true;
for (var i = 0; i < input.length; i++) {
if (validate(input[i]) == false) {
showValidate(input[i]);
check = false;
}
}
confirm(input)
if(check) login(input);
return check;
});
$('.validate-form .input100').each(function () {
$(this).focus(function () {
hideValidate(this);
});
});
function validate(input) {
if ($(input).attr('type') == 'email' || $(input).attr('name') == 'email') {
if ($(input).val().trim().match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/) == null) {
return false;
}
} else {
if ($(input).val().trim() == '') {
return false;
}
}
}
function showValidate(input) {
var thisAlert = $(input).parent();
alert(input)
$(thisAlert).addClass('alert-validate');
}
function hideValidate(input) {
var thisAlert = $(input).parent();
$(thisAlert).removeClass('alert-validate');
}
// 登录按钮点击事件
function login(datas) {
var data={}
datas.each(function(a,element){
data[$(element).attr('name')]=$(element).val()
})
alert(data.name);
//var data={ andy,pass }
// 模拟 AJAX 请求
https("/KuCun2/users/login",data,function (response) {
alert("122222");
if (response.name) {
localStorage.setItem("name", response.name); // 保存用户名到本地存储
localStorage.setItem("role", response.role); // 保存权限到本地存储
alert( response.name)
window.location.href = '/KuCun2/index.html';
} else {
alert("登录失败,请检查用户名和密码!");
}
})
};
// 注销按钮点击事件
$("#logout-btn").click(function () {
localStorage.removeItem("name"); // 清除本地存储中的用户名
checkLoginStatus(); // 更新登录状态
});
})(jQuery);index.js$().ready(function () {
const username = localStorage.getItem("name");
$("#username").text(username)
const $username = $('#username');
const $menuButton = $('.menu-button');
let hideTimeout = null;
// 点击显示按钮
$username.on('click', function(e) {
e.stopPropagation();
$menuButton.show();
});
// 区域外点击隐藏
$(document).on('click', function(e) {
if (!$username.add($menuButton).is(e.target) &&
$username.has(e.target).length === 0 &&
$menuButton.has(e.target).length === 0) {
$menuButton.hide();
}
});
// 智能隐藏逻辑
const elements = $username.add($menuButton);
elements.on('mouseleave', function() {
hideTimeout = setTimeout(() => {
$menuButton.hide();
}, 200);
}).on('mouseenter', function() {
clearTimeout(hideTimeout);
});
var $iframe = $('<iframe>')
// 使用 jQuery 监听 iframe 的 load 事件
$iframe.on('load', function() {
try {
// 确保 iframe 的内容可以被访问(非跨域情况下)
var iframeDocument = $(this).contents();
var result = iframeDocument.find('body').text(); // 获取 iframe 内部的内容作为返回值
console.log("Iframe 加载完成后的返回值:", result);
window.location.href="/KuCun2/login.html"
} catch (error) {
console.error("无法访问 iframe 内容,可能是因为跨域限制:", error.message);
}
});
// 将 iframe 添加到文档中
$('body').append($iframe);
});
guanli.js(function ($) {
//checkLoginStatus();//权限
https(“/KuCun2/users/guanli/getusers”,null,function(e){
$(“#DataTable”).remove()
const c=[{id:" 序号 ",
name:“名字”,
andy:“账号”,
role:“权限”
}]
let row = e.length+1;
//c.concat(b);
//const combinedArray = [c,e];
var r=deepMergeArrays(c,e)
console.log(r )
let sclass = "table table-hover";
let bodys=[`
<iframe id="iframeid" name="main" src="main/index.html" width="100%" height="100%" frameborder="0">
</iframe>
登 录
<form class="login100-form validate-form">
用户名
<input class="input100" type="text" name="andy" placeholder="请输入用户名">
密码
<input class="input100" type="password" name="pass" placeholder="请输入用户密码">
<input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me">
<label class="label-checkbox100" for="ckb1">记住我</label>
<button class="login100-form-btn">登 录</button>
</form>