实现登录功能

然后再创建login.css存放于在static下,css目录中,id 为 content 的 样式;

#content {margin-left: 220px;margin-right: 1420px;margin-top: 100px;margin-bottom: auto;background-color: orange;}

创建login.html登录页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录</title><!-- 如何引入本地css文件--><link rel="stylesheet" th:href="@{/css/login.css}"/>
</head>
<body>
<div id="content"><!-- 错误是提示--><label id="errorMsg" style="color: crimson">[[${errorMsg}]]</label><form id="login_form" action="/login" method="post">姓名:<input type="text" id="uname" name="uname"><br/>密码:<input type="password" id="password" name="password"><br/><button onclick="login()">登录</button></form>
</div>
</body>
</html>

前面的这一部分是前端的,下面来把后端代码给写完:

UserRepository中添加方法的定义:

//通过用户名和密码查找用户
List<User> findByUnameAndPassword(String uname, String password);

UserService和实现类中添加方法如下:

/通过用户名和密码查找用户
List<User> findByUnameAndPassword(String uname, String password);
UserService和实现类中添加方法如下:// UserService
User login(User user);@Service
//把事务注解放在类上了,这样下面就不需要每次都在方法写这个注解了
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {//......@Overridepublic User login(User user) {List<User> userList = userRepository.findByUnameAndPassword(user.getUname(), user.getPassword());//防止有多个用户名相同,并且密码也相同的用户if (!CollectionUtils.isEmpty(userList)) {return userList.get(0);}return null;}
}

UserController中添加方法如下:

@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
public String loginPage(Model model) {return "login";
}@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Model model, User user) {User result = userService.login(user);if (result != null) {//登录成功,跳转到用户列表return "redirect:/userList";}//不成功,提示model.addAttribute("errorMsg", "用户名或密码不正确");return "login";
}

启动项目,访问

http://localhost:8080/loginPage

进入登录页面。

输入用户名密码。密码错误:

输入正确的用户名和密码,那么跳转到用户列表。

这样,我们一个简单的登录功能就搞定了。

如果我们需要在修改用户信息的时候,校验是否已经登录,怎么办呢?

拦截器

创建自定义的拦截器并实现HandlerInterceptor接口 。

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class SessionInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//session校验Object object = request.getSession().getAttribute("users");if (null == object) {response.sendRedirect("/loginPage");return false;}return true;}
}

创建一个java类继承WebMvcConfiguraeAdapter并重写addInterceptor方法(该类用来添加配置拦截器在该类中添加配置拦截器,以及配置过滤)。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration
public class MyInterceptor extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//可以添加多个拦截registry.addInterceptor(new SessionInterceptor())//也可以添加多个拦截路径,"/**"拦截所有.addPathPatterns("/update/**");}
}

再把登录Controller方法调整,把session信息存进去。

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Model model, User user, HttpServletRequest request) {User result = userService.login(user);if (result != null) {//用户信息保存在sessionrequest.getSession().setAttribute("users", user.getUname());return "redirect:/userList";}model.addAttribute("errorMsg", "用户名或密码不正确");return "login";
}

再次访问用户列表:

http://localhost:8080/userList

这时候,我们访问修改用户信息这个功能,跳转到了登录页面。

登录后,再次访问修改用户信息这个功能。

这样便来到用户信息修改页面。

到此,我们就实现了一个简单的session来接校验。

如果,我们服务器重启后,session就没了,因为session是保存在我们服务端的,并且还是在服务器内存里的。

session分布式有四种方案

方案一:客户端存储

直接将信息存储在cookie中,cookie是存储在客户端上的一小段数据,客户端通过http协议和服务器进行cookie交互,通常用来存储一些不敏感信息

缺点

  • 数据存储在客户端,存在安全隐患。

  • cookie存储大小、类型存在限制。

  • 数据存储在cookie中,如果一次请求cookie过大,会给网络增加更大的开销。

方案二:session复制

session复制是小型企业应用使用较多的一种服务器集群session管理机制,在真正的开发使用的并不是很多,通过对web服务器(例如Tomcat)进行搭建集群。

缺点

session同步的原理是在同一个局域网里面通过发送广播来异步同步session的,一旦服务器多了,并发上来了,session需要同步的数据量就大了,需要将其他服务器上的session全部同步到本服务器上,会带来一定的网路开销,在用户量特别大的时候,会出现内存不足的情况。

优点

服务器之间的session信息都是同步的,任何一台服务器宕机的时候不会影响另外服务器中session的状态,配置相对简单

Tomcat内部已经支持分布式架构开发管理机制,可以对tomcat修改配置来支持session复制,在集群中的几台服务器之间同步session对象,使每台服务器上都保存了所有用户的session信息,这样任何一台本机宕机都不会导致session数据的丢失,而服务器使用session时,也只需要在本机获取即可。

如何配置?

在Tomcat安装目录下的config目录中的server.xml文件中,将注释打开,tomcat必须在同一个网关内,要不然收不到广播,同步不了session,在web.xml中开启session复制:。

方案三:session绑定:

Nginx是一款自由的、开源的、高性能的http服务器和反向代理服务器

Nginx能做什么?

反向代理、负载均衡、http服务器(动静代理)、正向代理

如何使用nginx进行session绑定

我们利用nginx的反向代理和负载均衡,之前是客户端会被分配到其中一台服务器进行处理,具体分配到哪台服务器进行处理还得看服务器的负载均衡算法(轮询、随机、ip-hash、权重等),但是我们可以基于nginx的ip-hash策略,可以对客户端和服务器进行绑定,同一个客户端就只能访问该服务器,无论客户端发送多少次请求都被同一个服务器处理。

缺点

  • 容易造成单点故障,如果有一台服务器宕机,那么该台服务器上的session信息将会丢失

  • 前端不能有负载均衡,如果有,session绑定将会出问题

优点

  • 配置简单

方案四:基于redis存储session方案

优点

  • 这是企业中使用的最多的一种方式

  • spring为我们封装好了spring-session,直接引入依赖即可

  • 数据保存在redis中,无缝接入,不存在任何安全隐患

  • redis自身可做集群,搭建主从,同时方便管理

缺点

多了一次网络调用,web容器需要向redis访问。

一般会将web容器所在的服务器和redis所在的服务器放在同一个机房,减少网络开销,走内网进行连接。

来源:http://45dwz.com/xeP0J

实现基于redis分布式存储session方案

安装Redis,这里就不说了,不会安装可以联系我。

集成Redis

添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
</dependency>

添加Redis配置

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000

将session添加入Redis中

在启动类上添加@EnableRedisHttpSession注解。

@SpringBootApplication
@EnableRedisHttpSession
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

启动项目,然后,再次登录后,便可以在Redis里查到了

再次重启项目后,发现修改用户信息的时候,并不需要重新登录了。

到此,基于Redis分布式存储session方案就已经搞定了。

总结

本文首先是实战了登录功能,其次接着实现了校验session拦截处理,然后总结出session分布式四种方案,最后实现了基于redis存储session的方案。

实战 用户登录、session校验、分布式存储session相关推荐

  1. Springboot自定义注解实现用户登录状态校验(一)

    Springboot自定义注解实现用户登录状态校验(一) 拦截器方式 定义注解类 import java.lang.annotation.*;/*** @author:小飞猪* @date:2020/ ...

  2. 网页用户登录权限校验的两种实现方式

        网页登录界面进行登录后,如果不进行登录校验,则在其它页面无法知道该用户是否进行了登录.故需要对用户的登录进行校验,这里将介绍两种登录校验的方式.分别为利用自定义行为过滤器进行登录校验,另外一种 ...

  3. asp带验证码的用户登录及校验代码实现

    在参考了各种资料之后,实现了用户登录模块.主要难点集中在随机验证码的实现以及验证码在页面间的传递操作.具体实现代码如下: login.asp: <% FUNCTION GEN_KEY(digit ...

  4. LDAP用户登录认证校验 及 LDAP分页查询

    某天,老大说,给我一个需求,支持LDAP用户登录,一听,哇,这是啥 啥 啥.经过刻苦努力Ctrl+C/V,终于搞出来了,上代码! 了解一下,LDAP(Lightweight Directory Acc ...

  5. C#笔记(学生管理系统实战 - 用户登录)

    总算忙过一段时间了,两个月前看了一点点关于 C# 的实战视频,现在看回来居然忘得七七八八,果然学习还是要写笔记,好记性不如烂笔头.. 1 项目框架 用户界面模块 数据访问模块 DAL(即如同 Serv ...

  6. CAS单点登录 - 用户登录与校验

    /*** CAS的统一登录接口* 目的:* 1. 登录后创建用户的全局会话 -> uniqueToken* 2. 创建用户全局门票,用以表示在CAS端是否登录 -> userTicket* ...

  7. JavaWeb中使用session保持用户登录状态

    使用session保持用户登录状态 // 登录 成功// 保存用户登录的信息到Session域中req.getSession().setAttribute("user", logi ...

  8. Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

    一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性 ...

  9. java登陆挤下去代码_application作用域实现用户登录挤掉之前登录用户代码

    一.实现思想 1.application(servletcontext)是保存在服务器端的作用域,我们在application中保存两种形式的键值对:1:,2: 2.每当一个用户登录时(将生成一个新的 ...

最新文章

  1. python使用imbalanced-learn的TomekLinks方法进行下采样处理数据不平衡问题
  2. python 学习之 PythonAdvance2
  3. 学习OCS客户端定制
  4. Redis 如何分布式,来看京东金融的设计与实践
  5. 用户请求接口信息日志记录
  6. 获取界面url_PHP调用百度地图接口,根据IP地址获取地区
  7. 辽宁交通高等专科学校有计算机专业吗,辽宁省交通高等专科学校可以转专业吗,辽宁省交通高等专科学校新生转专业政策...
  8. 怀念一下过去的人和事
  9. 【英语学习】【WOTD】horticulture 释义/词源/示例
  10. android怎么注释代码块,Android.mk 代码注释
  11. dis的前缀单词有哪些_英语单词II词根词缀记忆法:必背英语前缀DIS (DI, DIF)
  12. 基于vue + element 的后台管理系统
  13. 表单式工作流功能模块设计方案
  14. 中美计算机软件著作权登记差异与比较
  15. 用Python做一个Mean Rerversion策略
  16. 2019 CSS经典面试题(史上最全,持续更新中...)
  17. 推荐一些国内外文献检索与免费下载的网站
  18. html调用手机NFC,NFC门禁模拟-教你用NFC手机模拟门禁卡
  19. 道一云与畅捷通T+对接集成获取报销信息列表=>凭证创建
  20. 2023年产品经理需要考的证书,NPDP含金量真高

热门文章

  1. office插件开发_Visual Studio Code有哪些你常用的插件?
  2. KALI LINUX文件名乱码,在kali linux之下 下载并解压的文件名呈现乱码 解决方案
  3. linux 在硬盘中创建文件系统,linux mkfs命令创建Linux文件系统
  4. java重要基础知识点_必看 | 新人必看的Java基础知识点大梳理
  5. PTA数据结构与算法题目集(中文)7-25
  6. 链表 + 数组模拟链表
  7. mysql报错注入原理,MySQL报错注入
  8. 在java中建个jsp文件_第一个jsp页面
  9. 树的懒加载怎么用ajax调接口,ElementUI tree树形控件的懒加载使用
  10. java正立三角形_JAVA 打印三角形