【JavaWeb学习Day20】
- 开源代码
- 2025-09-20 04:42:02

Tlias智能学习系统 员工登录
三层架构:
Controller:1.接收请求参数(用户名,密码)2.调用Service方法3.响应结果
具体实现:
/** * 登录 */ @PostMapping("/login") public Result login(@RequestBody Emp emp){ log.info("登录:{}",emp); LoginInfo info = empService.login(emp); if(info != null){ return Result.success(info); } return Result.error("用户名或密码错误"); }Service:1.根据用户名和密码查询员工信息2.判定,组装数据并放回
具体实现:
/** * 登录 */ @Override public LoginInfo login(Emp emp) { //1.调用Mapper接口,根据用户名和密码查询员工信息 Emp e = empMapper.selectByUsernamePassword(emp); //2.判断:判断是否存在这个员工,如果存在,组装登录信息 if(e!=null){ log.info("登录成功,员工信息:{}",e); return new LoginInfo(e.getId(),e.getUsername(),e.getName(),""); } //3.不存在,放回null return null; }Mapper:SQL:select * from emp where username ='shinaian' and password ='123456';
具体实现:
/** * 登录 */ @Select("select id,username,name from emp where username = #{username} and password = #{password}") Emp selectByUsernamePassword(Emp emp);联调测试:
问题:在未登录的情况下,我们也可以直接访问部门管理、员工管理等功能
需求:只有在员工登录成功,才可以访问后台系统中的数据。
登录校验:登录标记:用户登录成功之后,在后续的每一次请求中,都可以获取到该标记。【会话技术】
统一拦截:过滤器Filter、拦截器:Interceptor
会话技术:
会话:用户打卡浏览器,访问web浏览器资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享资源。
会话跟踪方案:
1.客户端会话跟踪技术:Cookie
2.服务端会话跟踪技术:Session
/** * HttpSession演示 */ @Slf4j @RestController public class SessionController { //设置Cookie @GetMapping("/c1") public Result cookie1(HttpServletResponse response){ response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie return Result.success(); } //获取Cookie @GetMapping("/c2") public Result cookie2(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if(cookie.getName().equals("login_username")){ System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie } } return Result.success(); } @GetMapping("/s1") public Result session1(HttpSession session){ log.info("HttpSession-s1: {}", session.hashCode()); session.setAttribute("loginUser", "tom"); //往session中存储数据 return Result.success(); } @GetMapping("/s2") public Result session2(HttpSession session){ log.info("HttpSession-s2: {}", session.hashCode()); Object loginUser = session.getAttribute("loginUser"); //从session中获取数据 log.info("loginUser: {}", loginUser); return Result.success(loginUser); } }3.令牌技术
JWT令牌—介绍:
全称:JSON Web Token( jwt.io/)
定义了一种简洁、自包含的格式,用于在通信双方以json数据格式安全的传输信息。
组成:
1.Header(头),记录令牌类型、签名算法等。例如:{"alg":"HS256","type":"JWT"}
2.Payload(有效载荷),携带一些自定义信息、默认信息等。例如:{"id":"1","username":"Tom"}
3.Signature(签名),放置Token被篡改、确保安全性。将header、payload融入,并加入指定秘钥,通过指定签名算法计算而来。
JWT令牌—生成/解析:
引入jjwt的依赖。
调用官方提供的工具类Jwts来生成或解析jwt令牌。
报错:JWT令牌被篡改或过期失效了
(注意事项:JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的)
/** * 生成JWT令牌 */ @Test public void testGenerateJwt(){ Map<String, Object> dataMap = new HashMap<>(); dataMap.put("id",1); dataMap.put("username","admin"); String jwt = Jwts.builder() .signWith(SignatureAlgorithm.HS256, "aXRoZWltYQ==") .addClaims(dataMap) .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置过期时间 pact(); System.out.println(jwt); } /** * 解析令牌 */ @Test public void testParseJWT(){ String token = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImV4cCI6MTc0MDczMDEwNX0.BtOnJwrDgsAZTf3v-RJOhTwL7CESndEkl7gTU3XfgHU"; Claims claims = Jwts.parser() .setSigningKey("aXRoZWltYQ==")//指定密钥 .parseClaimsJws(token)//解析令牌 .getBody();//获取自定义信息 System.out.println(claims); } 登录功能(令牌)生成token(令牌)
1.定义JWT令牌操作工具类。(基于ai)
2.登录完成后,调用工具类生成JWT令牌,并放回。
public class JwtUtils { private static String signKey = "SVRIRUlNQQ=="; private static Long expire = 43200000L; /** * 生成JWT令牌 * @return */ public static String generateJwt(Map<String,Object> claims){ String jwt = Jwts.builder() .addClaims(claims) .signWith(SignatureAlgorithm.HS256, signKey) .setExpiration(new Date(System.currentTimeMillis() + expire)) pact(); return jwt; } /** * 解析JWT令牌 * @param jwt JWT令牌 * @return JWT第二部分负载 payload 中存储的内容 */ public static Claims parseJWT(String jwt){ Claims claims = Jwts.parser() .setSigningKey(signKey) .parseClaimsJws(jwt) .getBody(); return claims; } }Service层代码修改:
/** * 登录 */ @Override public LoginInfo login(Emp emp) { //1.调用Mapper接口,根据用户名和密码查询员工信息 Emp e = empMapper.selectByUsernamePassword(emp); //2.判断:判断是否存在这个员工,如果存在,组装登录信息 if(e!=null){ log.info("登录成功,员工信息:{}",e); //生成Jwt令牌 Map<String, Object> claims = new HashMap<>(); claims.put("id",e.getId()); claims.put("username",e.getUsername()); String jwt = JwtUtils.generateJwt(claims); return new LoginInfo(e.getId(),e.getUsername(),e.getName(),jwt); } //3.不存在,放回null return null; } 过滤器(Filter):概念:Filter过滤器,是javaWeb三大组件(Servlet、Filter、Listener)之一。
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。
Filter快速入门:
1.定义Filter:定义一个类,实现Filter接口,并实现其所有方法。
2.配置Filter:Filter类上加@WebFilter注解,配置拦截路径。引导类上加@ServletComponentScan开启Servlet组件支持。
public class DemoFilter implements Filter { //初始化方法,web服务器启动的时候执行,只执行一次 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("拦截到了方法。。。。。"); //放行 filterChain.doFilter(servletRequest,servletResponse); } //拦截到请求之后,执行,会执行多次 @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("init 初始化方法。。。。"); } //销毁方法,web服务器关闭的时候执行,只执行一次 @Override public void destroy() { log.info("destroy 销毁方法。。。。"); }登录校验Filter:
@Slf4j @WebFilter("/*") public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //1.获取请求路径 String requestURI = request.getRequestURI(); //2.判断是否是登录请求,如果路径中包含/login,说明是登录操作,放行 if(requestURI.contains("/login")){ log.info("登录请求,放行"); filterChain.doFilter(request,response); } //3.获取请求头中的token String token = request.getHeader("token"); //4.判断token是否存在,如果不存在,说明用户没有登录,放回错误信息(响应401状态码) if(token == null||token.isEmpty()){ log.info("令牌为空,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } //5.如果token存在,校验令牌,如果校验失败,放回错误信息(401状态码) try { JwtUtils.parseJWT(token); } catch (Exception e) { log.info("令牌非法,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } //6.校验通过,放行 log.info("令牌合法,放行"); filterChain.doFilter(request,response); } }详解(执行流程、拦截路径、过滤器链):
执行流程:先执行放行前逻辑,对应资源访问完成后,执行放行后逻辑。
拦截路径:
(Filter可根据需求,配置不同的拦截资源路径)
过滤器链:
介绍:一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链。
顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。
拦截器Interceptor快速入门:
概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,主要用来动态拦截控制器方法的执行。
作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先定的代码。
//实现HandlerIntercepter @Slf4j @Component public class DemoInterceptor implements HandlerInterceptor { //在目标资源方法运行之前运行- 返回值:true 放行,false 不放行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("preHandle...."); return true; } //在目标资源方法运行之后运行 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle"); } //视图渲染完毕后运行 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion"); } } //定义一个配置类实现WebMvcConfigurer接口,注册拦截器(/**) /** * 配置类 */ @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private DemoInterceptor demoInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(demoInterceptor).addPathPatterns("/**");//拦截所有请求 } }令牌校验Interceptor:
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1.获取请求路径 String requestURI = request.getRequestURI(); //2.判断是否是登录请求,如果路径中包含/login,说明是登录操作,放行 if(requestURI.contains("/login")){ log.info("登录请求,放行"); return true; } //3.获取请求头中的token String token = request.getHeader("token"); //4.判断token是否存在,如果不存在,说明用户没有登录,放回错误信息(响应401状态码) if(token == null||token.isEmpty()){ log.info("令牌为空,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } //5.如果token存在,校验令牌,如果校验失败,放回错误信息(401状态码) try { JwtUtils.parseJWT(token); } catch (Exception e) { log.info("令牌非法,响应401"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } //6.校验通过,放行 log.info("令牌合法,放行"); return true; }详解:
拦截路径:(可根据需要配置拦截路径)
执行流程(过滤器和拦截器同时存在):
Filter和Interceptor区别:
1.接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口
2.拦截范围不同:过滤器Filter会拦截所有资源,而Interceptor只会拦截Spring环境中的资源
【JavaWeb学习Day20】由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【JavaWeb学习Day20】”