记录一下在SpringBoot中实现简单的登录认证

代码参考博客:

https://blog.csdn.net/weixin_37891479/article/details/79527641

在做学校的课设的时候,发现了安全的问题,就不怀好意的用户有可能跳过登录直接访问系统的界面和使用里面的功能,于是想为系统加个安全验证。现在常用的安全框架我知道的就是Shiro还有SpringSecurity,但这次我不打算用框架,采用拦截器filter和session技术实现了一个基于session的登录认证。

先简单地说一下原理

session和cookie介绍

首先要知道,session是什么。  我们知道HTTP是个无状态的协议,在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。  

而cookie,就是把用户的数据写在浏览器,session是放在服务器的内存中的。   session和cookie都是为了跟踪与用户的会话而诞生的技术

 

然后cookie和session的简单区别:

  • Cookie是把用户的数据写给用户的浏览器。
  • Session技术把用户的数据写到用户独占的session中。
  • Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

 

session的实现原理:

  1. 服务器是如何实现一个session为一个用户的浏览器服务的呢???(千万要搞清楚,服务器是对每个用户的浏览器都创建一个session对象,也就是说每个浏览器用户都有一块内存来存他们的信息!!!)
  2. 在一个用户向服务器发出请求后,服务器会看这个浏览器所夹带的cookie有没有sessionId这一项,如果没有,则说明这个用户是第一次访问这个服务器,然后服务器为这个浏览器用户创建一个session和一个独一无二的sessionid,并把这个id以cookie的形式写回给客户机。
  3. 后面客户端访问服务器,都会带着这个sessionid去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。
  4. 额如果浏览器也就是客户端禁止使用cookie怎么办,有两个技术:url重写 和 隐藏表单域   其实思路都是 想办法把这个sessionid传给服务器,让服务器找到正确的session和这个浏览器客户机对应。

 

实现思路:

登录成功的时候,在该浏览器用户所对应的session中,新建一个key为“hasLoginedUsersMap”,值为一个Map<String, Object> hasLoginedUsersMap的键值对,顾名思义,就是一个记录了该客户端所登陆过的用户信息的Map。(为什么不直接记录一个"user",User的键值对,因为考虑到一个浏览器可能用多个用户去登录……)然后这个Map里面,每一个键值对就是("userId",User),也就是键为用户id,然后值为这个User对象。  所以登录成功后,就先看session里面有没有这个Map,若没有则建立一个并在这个Map里面添加这个userid和这个user;如果有这个Map就在这个Map中添加这个用户的userId和User信息。

每个用户请求过来,先被Filter拦截下来,经过Filter处理后才到SpringMVC的servlet。在Filter中,看这个浏览器用户的session,看有没hasLoginedUsersMap这个Map,如果有,就说明该用户登录过了,可以继续访问,如果没有这个Map,就重定向到别的界面,就不让他访问原来的资源。(我的主页的请求中带有用户的userId,如果是主页请求,就会去Map中看有没有这个UserId的信息,如果有就登录过,没有的话就不让他访问。)

 

 

下面贴下代码,登录和注销还有filter中的拦截代码就不上了,主要看看Filter的注册:

查到在Springboot中一般有两种注册这个FIlter的方法:

1.注解注册法:

在过滤器上添加WebFilter注解
在启动类添加ServletComponentScan注解:

@WebFilter(filterName = "sessionFilter",urlPatterns = {"/*"})
public class SessionFilter implements Filter {
@SpringBootApplication
@ServletComponentScan
public class FileUploadApplication {

    public static void main(String[] args) {
        SpringApplication.run(FileUploadApplication.class, args);
    }


}

 

2.javaConfig注册:

package com.stuPayment.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.stuPayment.util.LoginFilter;

@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean loginSessionFilter() {//这个类应该是Spring给我们拿来初测filter的
        
        FilterRegistrationBean registration = new FilterRegistrationBean();//新建过滤器的注册类
        
        registration.setFilter(new LoginFilter());//添加我们写好的filter
        
        registration.addUrlPatterns("/*");//设置filter的过滤的url模式
        
        return registration;//返回这个就是Spring会帮你注入的那个对象
        
    }
    
}

 

这里提一下:

当有多个过滤器需要按顺序执行时怎么办?
使用注解的配置方法不能配置顺序,但是可以通过过滤器名字的字典顺序实现顺序过滤(比如AFilter就会在BFilter前执行),显然这种方法看起来不怎么正经。
但是我们可以使用第二种配置方法.
通过给注册类设置order,order越小,执行优先级越高

 @Bean
    public FilterRegistrationBean someFilterRegistration1() {
        //新建过滤器注册类
        FilterRegistrationBean registration = new FilterRegistrationBean();
        // 添加我们写好的过滤器
        registration.setFilter( new SessionFilter());
        // 设置过滤器的URL模式
        registration.addUrlPatterns("/*");
        //设置过滤器顺序
        registration.setOrder(1);
        return registration;
    }

 

posted @ 2018-07-10 21:46  汪神  阅读(12512)  评论(0编辑  收藏  举报