原创声明:本文为本人原创作品,绝非他处摘取,转载请联系博主

相信大家在各大网站都会遇到,登录时,在登录框出现下次免登陆/一个月免登陆的类似选项,本次博文就是讲解如何实现,在这记录一下,也算是做个备忘录合集,如果文中有错,欢迎大家指出

为啥说自登陆一次呢,因为当访问某个页面时,如果第一次自动登录失败时,你下次刷新访问时还再次走自动登录流程,就会出现死循环。

本篇博文代码示例框架为Spring MVC,下面就讲解实现该功能的需要掌握哪些知识:cookies与过滤器

1.cookies

何为Cookies:Cookies为 Web 应用程序保存用户相关信息提供了一种有用的方法。例如,当用户访问您的站点时,您可以利用 Cookie 保存用户首选项或其他信息,这样,当用户下次再访问您的站点时,应用程序就可以检索以前保存的信息。

我们看一下是如何保存cookies和如何删除cookies

  • 保存cookies
String newUserName = null;
try {
newUserName = URLEncoder.encode(username, "UTF-8");//把用户名转码,防止用户名是中文,cookies保存中文取出会乱码
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Cookie nameCookie = new Cookie("username", newUserName);
String pwdMd5Cook = MD5Util.MD5(Pwd);
Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密后的密码
nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用户名保存一年
pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密码保存30天
// 发送Cookie信息到浏览器
response.addCookie(nameCookie);
response.addCookie(pwdCookie);

删除cookies,删除很简单,但值得注意的时,删除cookies,跟保存cookies一定要在同一个控制层,不然会找不到保存的cookies,导致删除不了

Cookie cookie = new Cookie("pwd", null);
cookie.setMaxAge(0);// 删除密码cookie
response.addCookie(cookie);

2.Filter-过滤器

Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

实现方法:继承Filter接口,并实现其doFilter方法。在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源

<filter>指定一个过滤器。
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
<filter-class>元素用于指定过滤器的完整的限定类名。
<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
<servlet-name>指定过滤器所拦截的Servlet名称。
<filter>
<filter-name>suicaiFilter</filter-name>
<filter-class>com.suicai.filter.suicaiFilter</filter-class>
</filter> <filter-mapping>
<filter-name>suicaiFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

下面看一下实际应用代码:

public class suicaiFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)request;
HttpServletResponse res=(HttpServletResponse)response;
HttpSession session = req.getSession();
String requestURI = req.getRequestURI();
String param = req.getQueryString();
String url = req.getServletPath();
if(param!=null){
url = url+"?"+param;
}
if(requestURI.contains("js") || requestURI.contains("css") || requestURI.contains("images")){
//不过滤css,js,images等静态资源
chain.doFilter(request, response);
}else if(requestURI.contains("/info/")||requestURI.contains("/gys/")){
//过滤前台访问页面,跟前台个人中心(供应商后台),自动登录一次,登录不成功不进行操作,个人中心登录不成功,则跳到登录页面
ProviderInfo providerInfo = (ProviderInfo) session.getAttribute("providerInfo_gys");
String IsAutomaticLogin = (String) session.getAttribute("IsAutomaticLogin");//是否已经走过自动登录流程标识
if(requestURI.contains("/info/") && !requestURI.contains("/login")){
//访问门户等不需要必须登录的(登录除外),只尝试登录一次,如果不成功,不进行操作
if(providerInfo==null && IsAutomaticLogin == null){
req.getSession().setAttribute("goURL", url);
res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
}else if(providerInfo==null && IsAutomaticLogin != null ){
chain.doFilter(request, response);
}else{
chain.doFilter(request, response);
}
}else if(requestURI.contains("/gys/")){//访问个人中心,自登陆一次,不成功跳转到登录页面
if(providerInfo==null && IsAutomaticLogin == null){
req.getSession().setAttribute("goURL", url);
res.sendRedirect(req.getContextPath() + "/common/automaticLogin");
}else if(providerInfo==null && IsAutomaticLogin != null ){
session.setAttribute("redirectUrl", url);
res.sendRedirect(req.getContextPath() + "/login.jsp?redirectUrl="+url);
}else{
chain.doFilter(request, response);
}
}else{
chain.doFilter(request, response);
}
}else{
//不过滤
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}

从代码中可知,需要一个是否已经自动登录过的标识(IsAutomaticLogin),该标识是在走自动登录时(不管成不成功)保存起来的

3.结合上面提供知识,下面为整体代码展示,如发现不对地方,欢迎大家指出

@Controller
@RequestMapping("/common")
public class CommonController{
/**
* 自动登录方法
* @param request
* @param response
* @param username
* @param pwd
* @param ProviderInfo 供应商账户信息model
* @return
*/
@RequestMapping("/automaticLogin")
public String automaticLogin(HttpServletRequest request,ServletResponse response,@CookieValue(value = "username", required = false) String username,@CookieValue(value = "pwd", required = false) String pwd,ProviderInfo ProviderInfo) {
// 保存需求登录前的链接
String goURL = (String) session.getAttribute("goURL");
if (username == null) {//cookies中没有用户名,肯定不需要自动登录
session.setAttribute("IsAutomaticLogin", "0");
return "redirect:" + goURL;
} else {
try {
username = URLDecoder.decode(username, "UTF-8");//转义,防止中文
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
// cookie失效 session一定为空,因为登录时,一定会把用户名保存在cookie中
if ("".equals(username) || username == null) {// 使用session登录不了,不进行任何操作,不在进入这个方法
session.setAttribute("IsAutomaticLogin", "0");
return "redirect:" + goURL;
} else {
// cookie中没有密码,判断session为不为空,如果为空,说明没有登录,如果不为空,说明,用户是选择不记住密码登录(所以cookie中没有密码)
if ("".equals(pwd) || pwd == null) {
ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
if (customer1 == null) {// 使用session登录不了,不进行任何操作,不在进入这个方法
session.setAttribute("IsAutomaticLogin", "0");
return "redirect:" + goURL;
} else {
// 已经登录,不再进入这个方法
return "redirect:" + goURL;
}
} else {
// cookie中有密码,判断session为不为空,如果为空,说明没有登录,如果不为空,说明已经登录
ProviderInfo customer1 = (ProviderInfo) session.getAttribute("providerInfo_gys");
if (customer1 == null) {// 当前没有登录,调用cookies中的用户名跟密码进行登录
// 进行自动登录操作,登录成功后返回原来页面
ProviderInfo customer3 = ValidateDate(username);
customer3.setPwd(pwd);
customer3.setAccountType(6);
ProviderInfo customer2 = infoService.login(customer3);//调用登录方法
if (customer2 == null) {// 自动登录失败,不再进入这个方法
session.setAttribute("IsAutomaticLogin", "0");
return "redirect:" + goURL;
} else {
// 登陆成功保存客户信息到session
session.setAttribute("providerInfo_gys",customer2);
return "redirect:" + goURL;
}
} else {
return "redirect:" + goURL;
}
}
}
}
/**
* 用户登陆
* @param request
* @param response
* @param cus
* @return
*/
@RequestMapping("/UserLogin")
@ResponseBody
public Map<String, Object> goLogin(HttpServletRequest request,HttpServletResponse response,@ModelAttribute("ProviderInfo") ProviderInfo cus) {
/*省略一些逻辑判断*/
cus.setPwd(MD5Util.MD5(Pwd));
ProviderInfo providerInfo = infoService.login(cus);
Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
if (providerInfo == null) {
// 登陆失败,重新跳转到登陆页面
map.put("error", "密码错误");
return map;
}else{
String newUserName = null;
if (remember_me.equals("1")) {// 有选择一个月免登录
try {
newUserName = URLEncoder.encode(username, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Cookie nameCookie = new Cookie("username", newUserName);
String pwdMd5Cook = MD5Util.MD5(Pwd);
Cookie pwdCookie = new Cookie("pwd", pwdMd5Cook);// 保存加密后的密码+"create"
nameCookie.setMaxAge(60 * 60 * 24 * 365);// 用户名保存一年
pwdCookie.setMaxAge(60 * 60 * 24 * 30);// 密码保存30天
// 发送Cookie信息到浏览器
response.addCookie(nameCookie);
response.addCookie(pwdCookie);
session.setAttribute("IsAutomaticLogin",null);
}else{//没有选择,删除上次可能已经选择自动登录时的密码
Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (Cookie cookie : cookies) {
cookieMap.put(cookie.getName(), cookie);
}
}
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookieMap.containsKey("pwd")) {
Cookie cookie = new Cookie("pwd", null);
cookie.setMaxAge(0);// 删除密码cookie
response.addCookie(cookie);
}
}
}
}
// 登陆成功,保存当前user信息,保存客户信息到session
map.put("ProviderInfo", providerInfo);
map.put("goURL", session.getAttribute("goURL"));
session.setAttribute("providerInfo_gys", providerInfo);
return map;
}else {
map.put("error", "该供应商账号不存在");
return map;
}
}
/**
* 注销
* @return
*/
@RequestMapping("/logout")
public String logout(HttpServletResponse response) {
Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (Cookie cookie : cookies) {
cookieMap.put(cookie.getName(), cookie);
}
}
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookieMap.containsKey("pwd")) {
Cookie cookie = new Cookie("pwd", null);
cookie.setMaxAge(0);// 删除密码cookie
response.addCookie(cookie);
}
}
}
session.setAttribute("providerInfo_gys", null);
return "/index";
}
}

到此,该功能示例讲解全部完成,如有不对的地方,欢迎大家在评论区指出。

基于cookie使用过滤器实现客户每次访问自登陆一次的更多相关文章

  1. 备忘录《一》基于cookie使用拦截器实现客户每次访问自登陆一次

    原创声明:本文为本人原创作品,绝非他处摘取,转载请联系博主 相信大家在各大网站都会遇到,登录时,在登录框出现下次免登陆/一个月免登陆的类似选项,本次博文就是讲解如何实现,在这记录一下,也算是做个备忘录 ...

  2. (26)基于cookie的登陆认证(写入cookie、删除cookie、登陆后所有域下的网页都可访问、登陆成功跳转至用户开始访问的页面、使用装饰器完成所有页面的登陆认证)

    获取cookie request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age ...

  3. 如何请求一个需要登陆才能访问的接口(基于cookie)---apipost

    在后台在开发.调试接口时,常常会遇到需要登陆才能请求的接口. 比如:获取登陆用户的收藏列表,此时,我们就需要模拟登陆状态进行接口调试了.如图: 今天,我们讲解利用ApiPost的环境变量,解决这种需要 ...

  4. 使用nginx sticky实现基于cookie的负载均衡

    在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...

  5. 使用nginx sticky实现基于cookie的负载均衡【转】

    在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...

  6. NGINX:sticky模块实现基于cookie的负载均衡

    Sticky模块 简述: 之前公司部署了一套网站及时发布系统,架构如下图所示:Nginx做前端代理,发布系统用tomcat运行,一台共享存储,一台数据库服务器:由于网站及时发布系统涉及到了用户登录操作 ...

  7. nginx第三方模块---nginx-sticky-module的使用(基于cookie的会话保持)

    目前的项目网站架构中使用了F5和nginx,F5用来做负载均衡,nginx只用作反向代理服务器.最近应客户的要求准备去掉F5,使用软负载.大家都知道nginx抗并发能力强,又可以做负载均衡,而且使用n ...

  8. Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录

    1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...

  9. 基于 Cookie 的 SSO 中间件 kisso

    kisso  =  cookie sso 基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞士军刀.欢迎大家使用 kisso !! kisso 帮助文档 ...

随机推荐

  1. 浅谈C#抽象类

    抽象类 先说个事,一个类实例化为一个实例.就是一只狗,实例化一下,就成了一只哈士奇(具体的二哈).但是,一个动物类实例化呐,成了啥? 压根就不能实例化.这,就是抽象类的概念引入. 概念:C#允许把类和 ...

  2. mybatis插入List集合数据

    处女帖 今天做完一个定时任务将一个表中的数据每天统计到另外一个表中,开始是用循环的方式向数据库添加,觉得数据库可能访问压力过大,所以就使用了mybatis的foreach标签来稍微的减少压力. 首先封 ...

  3. LeetCode 376. Wiggle Subsequence 摆动子序列

    原题 A sequence of numbers is called a wiggle sequence if the differences between successive numbers s ...

  4. cmapx 保存绘制好的图层

    研究了两天,如何保存一绘制好的图层,大致意思都说要使用mapInfo表,然后确定了可定和.TAB表有关.然而网上说的全是垃圾,也不能说全是垃圾,好歹我从中得到了一点点有用的信息,使用mapManage ...

  5. Linux svn服务的搭建

    一.yum安装svn yum -y install subversion   二.查看已安装的svn版本信息 svnserve --version   三.创建一个代码库 1.先创建一个目录 mkdi ...

  6. Excel基本操作1

    Excel的基本操作之二,录入及快速填充.不足之处,欢迎补充

  7. margin重叠

    margin重叠也就是我们常说的CSS 外边距合并,W3C给出如下定义: 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者 ...

  8. jquery获取文件名称

    $("#fileupload").on("change",function(){ var filePath=$(this).val(); if(filePath ...

  9. hdu3746 kmp求循环节

    CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, ...

  10. mysql sql语句

    1.数据库和表的操作 创建 create修改 alter删除 drop查看 show 1.1创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name    [crea ...