iframe和response.sendRedirect使用的问题

本文讨论了在使用Struts框架时,如何解决由于使用iframe导致的登录页面重定向问题,通过在jsp中使用js实现iframe区域的正确跳转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一般使用filter过滤用户是否登录,如果用户没有登陆则转向登陆页面,这时候可以使用response.sendRedirect()。

但当在页面上使用了iframe后,发现被重定向的只是父页面中的iframe区域,登陆页面内容显示在该区域中。说明在过滤器中发送重定向请求时,是在iframe页面发送的。

错误的代码如下

HttpServletRequest req = (HttpServletRequest) request;
User user = (User) req.getSession().getAttribute("user");
if (user == null)
{
	 ((HttpServletResponse) response).sendRedirect("/login/login.jsp");
}
chain.doFilter(request, response);
 因为response.sendRedirect()没有target属性,但html页面和js中有,于是,当判断出用户没有访问权限时,我们可以在jsp中使用js来转向到真正的登录页面。在filter类的doFilter方法中添加如下代码

HttpServletRequest req = (HttpServletRequest) request;
User user = (Visitor) req.getSession().getAttribute("user");
if (visitor == null)
{
	java.io.PrintWriter out = response.getWriter();
	out.println("<html>");
	out.println("<script>");
	out.println("window.open ('/login/login.jsp','_top')");
	out.println("</script>");
	out.println("</html>");
}
chain.doFilter(request, response);

但问题来了:我们在开发中如果使用了Struts框架的话,验证就是用一个Interceptor来做,而对应的jsp又是通过struts.xml配置的

根本不能控制response对象;

Interceptor代码:

package ray.interceptors;


import ray.tools.Consts;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class LoginInterceptor extends AbstractInterceptor  {

	private static final long serialVersionUID = 1L;
	private ActionContext context = null;
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		this.context = invocation.getInvocationContext();
		Object object = context.getSession().get(Consts.USERSESSION);
		if(object == null){
			return Action.LOGIN;
		} else {
			return invocation.invoke();
		}
	}
}

struts.xml

<span style="white-space:pre">		</span><global-results>
			<result name="error">/WEB-INF/error/error.jsp</result>
			<result name="login" type="dispatcher">/WEB-INF/jsp/login/login.jsp</result>
			<result name="input" type="redirectAction">
				<param name="actionName">defAction</param>
			</result>
		</global-results>
我们在login.jsp中使用一个技巧:

login.jsp:

<%@ page language="java" contentType="text/html"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="${applicationScope.basePath}">
<title>Insert title here</title>
</head>
<body>
<!-- 设置中间页,用来处理登陆页面在iframe中显示的情况 -->
	<script type="text/javascript">
		if(parent){
			parent.location.href="index.jsp";
		}
	</script>
</body>
</html>
这样的话,就可以在struts框架中让iframe中redirect时,改变top窗口的href了。



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/> <!-- lookup parent from repository --> </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> <!-- Spring Boot Starter Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <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> <!-- Optional: Lombok for reducing boilerplate code --> <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> <!-- Jackson Databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Jackson Core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <!-- Jackson Annotations --> <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> <div class=“frame-header”> <a class=‘frame-header-li’ style=“color:#fff”>峤丞木材仓库管理</a> <a id=“username” class=‘frame-header-li’ style=“color:#520”>峤丞木材仓库管理</a> <button class=“.menu-button” style=“”>注销</button> </div> <div class=“frame-body”> <div class=“frame-side”> <ul class=‘frame-ul’ style=“text-align:center;”> <li ><a href=“main/test.html” target=“main”>首页</a></li> <li><a href=“main/LuRul.html” target=“main”>材料录入</a></li> <li><a href="main/Guanli.html" target="main">材料录入</a></li> </ul> </div> <div class="frame-main"> <!-- 内容主体区域 --> <iframe id="iframeid" name="main" src="main/index.html" width="100%" height="100%" frameborder="0"> </iframe> </div> </div> </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> <div class=“limiter”> <div class=“container-login100”> <div class=“wrap-login100”> <div class=“login100-form-title” style=“background-image: url(images/bg-01.jpg);”> <span class=“login100-form-title-1”>登 录</span> </div> <form class="login100-form validate-form"> <div class="wrap-input100 validate-input m-b-26" data-validate="用户名不能为空"> <span class="label-input100">用户名</span> <input class="input100" type="text" name="andy" placeholder="请输入用户名"> <span class="focus-input100"></span> </div> <div class="wrap-input100 validate-input m-b-18" data-validate="密码不能为空"> <span class="label-input100">密码</span> <input class="input100" type="password" name="pass" placeholder="请输入用户密码"> <span class="focus-input100"></span> </div> <div class="flex-sb-m w-full p-b-30"> <div class="contact100-form-checkbox"> <input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me"> <label class="label-checkbox100" for="ckb1">记住我</label> </div> <div> <a href="javascript:" class="txt1">忘记密码?</a> </div> </div> <div class="container-login100-form-btn"> <button class="login100-form-btn">登 录</button> </div> </form> </div> </div> </div> <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=[`<table id='DataTable' class='text-center ${sclass}'>`] let table=$("#TableView") table.append(bodys) let te= table.find("table") $.each(r, function(index, value) { var tr="" var boo=false if(index==0){var tr="<thead>"; boo=false} tr+="<tr>" $.each(value, function(name,val) { if(name!="pass"){ if(name!="id"){ tr+=`<td name='${name}' ><div contenteditable='${name!="id"&&boo}' style='float: left;width: 70%'>${val}</div></td>`; }else{ tr+=`<td name='${name}' style='float: left;width: 70%'>${val}</td>`; } } }) tr+="</tr>" if(index==0){ tr+="</thead>"} te.append(tr) }); addRight("#DataTable"); // // let sclass = “table table-striped”; // let bodys=[<table id='DataTable' class='text-center ${sclass}'>] // // for(let i = -1; i <= row; i++) { // bodys.push(“<tr>”); // // if(i=-1){ // // for(var a in c[0]) { // // var bo= “<td><div contenteditable=‘true’ style=‘float: left;width: 70%’>”+c[0][a]+“</div>”; // bodys.push(bo) // // } // // // }else{ // // // for(let j = 0; j <= col; j++) { // if(j == 0) { // var bo = “<td><div style=‘text-align: center;height: 100%’>” + e[i][b[j]] + “#</div></td>”; // bodys.push(bo) // } else { // var bo= “<td><div contenteditable=‘true’ style=‘text-align: center;height: 100%’>” // + // // ‘<span class=“glyphicon glyphicon-remove-sign” style=“color: #999;font-size: 16px;” onclick=“Deleterow(this)” aria-hidden=“true”></span>’ // +“</div></td>”; // bodys.push(bo) // } // } // } // bodys.push( “</tr>”); // // } // bodys.push(“</table>”); // var s=bodys.join(‘’) // $(“#TableView”).append(s); // addRight(“#DataTable”); // }) })(jQuery) 登录后访问index.html会被重定向到login.html其他以页面不回,
06-01
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/> <!-- lookup parent from repository --> </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> <!-- Spring Boot Starter Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <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> <!-- Optional: Lombok for reducing boilerplate code --> <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> <!-- Jackson Databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Jackson Core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <!-- Jackson Annotations --> <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> <div class="frame-header"> <a class='frame-header-li' style="color:#fff">峤丞木材仓库管理</a> <a id="username" class='frame-header-li' style="color:#520">峤丞木材仓库管理</a> <button class=".menu-button" style="">注销</button> </div> <div class="frame-body"> <div class="frame-side"> <ul class='frame-ul' style="text-align:center;"> <li ><a href="main/test.html" target="main">首页</a></li> <li><a href="main/LuRul.html" target="main">材料录入</a></li> <li><a href="main/Guanli.html" target="main">材料录入</a></li> </ul> </div> <div class="frame-main"> <!-- 内容主体区域 --> <iframe id="iframeid" name="main" src="main/index.html" width="100%" height="100%" frameborder="0"> </iframe> </div> </div> </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> <div class="limiter"> <div class="container-login100"> <div class="wrap-login100"> <div class="login100-form-title" style="background-image: url(images/bg-01.jpg);"> <span class="login100-form-title-1">登 录</span> </div> <form class="login100-form validate-form"> <div class="wrap-input100 validate-input m-b-26" data-validate="用户名不能为空"> <span class="label-input100">用户名</span> <input class="input100" type="text" name="andy" placeholder="请输入用户名"> <span class="focus-input100"></span> </div> <div class="wrap-input100 validate-input m-b-18" data-validate="密码不能为空"> <span class="label-input100">密码</span> <input class="input100" type="password" name="pass" placeholder="请输入用户密码"> <span class="focus-input100"></span> </div> <div class="flex-sb-m w-full p-b-30"> <div class="contact100-form-checkbox"> <input class="input-checkbox100" id="ckb1" type="checkbox" name="remember-me"> <label class="label-checkbox100" for="ckb1">记住我</label> </div> <div> <a href="javascript:" class="txt1">忘记密码?</a> </div> </div> <div class="container-login100-form-btn"> <button class="login100-form-btn">登 录</button> </div> </form> </div> </div> </div> <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" /> // $(document).ready(function(){ // $("#submit").click(function(){ // // // $.ajax({ // url:"../users/login", // async:false, // data:JSON.stringify({ // andy:$("#andy").val(), // pass:$("#pass").val(), // name:$("#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=[`<table id='DataTable' class='text-center ${sclass}'>`] let table=$("#TableView") table.append(bodys) let te= table.find("table") $.each(r, function(index, value) { var tr="" var boo=false if(index==0){var tr="<thead>"; boo=false} tr+="<tr>" $.each(value, function(name,val) { if(name!="pass"){ if(name!="id"){ tr+=`<td name='${name}' ><div contenteditable='${name!="id"&&boo}' style='float: left;width: 70%'>${val}</div></td>`; }else{ tr+=`<td name='${name}' style='float: left;width: 70%'>${val}</td>`; } } }) tr+="</tr>" if(index==0){ tr+="</thead>"} te.append(tr) }); addRight("#DataTable"); // // let sclass = "table table-striped"; // let bodys=[`<table id='DataTable' class='text-center ${sclass}'>`] // // for(let i = -1; i <= row; i++) { // bodys.push("<tr>"); // // if(i=-1){ // // for(var a in c[0]) { // // var bo= "<td><div contenteditable='true' style='float: left;width: 70%'>"+c[0][a]+"</div>"; // bodys.push(bo) // // } // // // }else{ // // // for(let j = 0; j <= col; j++) { // if(j == 0) { // var bo = "<td><div style='text-align: center;height: 100%'>" + e[i][b[j]] + "#</div></td>"; // bodys.push(bo) // } else { // var bo= "<td><div contenteditable='true' style='text-align: center;height: 100%'>" // + // // '<span class="glyphicon glyphicon-remove-sign" style="color: #999;font-size: 16px;" onclick="Deleterow(this)" aria-hidden="true"></span>' // +"</div></td>"; // bodys.push(bo) // } // } // } // bodys.push( "</tr>"); // // } // bodys.push("</table>"); // var s=bodys.join('') // $("#TableView").append(s); // addRight("#DataTable"); // }) })(jQuery) 访问index.html会被重定向到login.html其他以页面不回
05-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值