登录解决方案-单体应用-Session登录(拦截器实现)-实现一个简单的登录

一、技术栈:

  SpringBoot + thymeleaf  前后不分离

  常用注解:@RequiredArgsConstructor  lombok的注解  标注了 此注解 获取相关bean对象时 不需要 再用@Autowird 进行依赖注入

二、前期准备

 需求

  1.        实现一个简单的登录
  2.        用户登录首页后进入登录页默认进入首页 + Aop加自定义注解 对每个接口进行访问控制
  3.        单点登录,同一账号  在A浏览器登录后 在B浏览器登录上将 A挤下来,跨机房(服务器)单点签退

 表

复制代码
/*
  适用数据库:MYSQL
  修改内容 创建用户表
  最后修改人:mangoubiubiu
  最后修改日期:2022.03.27
*/
CREATE TABLE huas_user
(
   id           VARCHAR(32) NOT NULL COMMENT '用户唯一id',
   oauth_id     VARCHAR(32) COMMENT '第三方登录应用id',
   oauth_type   VARCHAR(16) COMMENT '第三方应用名',
   user_name    VARCHAR(32) DEFAULT 'huas' COMMENT '用户名',
   nickname     VARCHAR(64) COMMENT '用户昵称',
   pwd          VARCHAR(32) NOT NULL COMMENT '用户密码',
   email        VARCHAR(50)  COMMENT '用户邮箱',
   avatar       VARCHAR(1000) COMMENT '用户头像',
   signature    VARCHAR(1000) COMMENT '个性签名' ,
   phone        VARCHAR(11) COMMENT '用户手机',
   sex          VARCHAR(3) COMMENT '性别 1 男 0女',
   is_deleted   TINYINT(1) UNSIGNED NOT NULL COMMENT '逻辑删除 1(true)已删除, 0(false)',
   update_time  VARCHAR (14) COMMENT '修改时间',
   create_time  VARCHAR (14) COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

-- Add comments to the table 
ALTER TABLE huas_user ADD CONSTRAINT HUAS_USER_KEY PRIMARY KEY (id);
COMMIT;

/*
  适用数据库:MYSQL
  修改内容 创建session信息表
  最后修改人:mangoubiubiu
  最后修改日期:2022.03.27
*/
CREATE TABLE huas_sessionid
(
   id           VARCHAR(32) NOT NULL COMMENT '主键',
   user_id      VARCHAR(32) NOT NULL COMMENT '用户id',
   session_id   VARCHAR(32) COMMENT '用户登录的session_id',
   addr         VARCHAR(15) COMMENT '用户请求的地址',
   port         VARCHAR(12) COMMENT '请求的ip',
   update_time  VARCHAR (14) COMMENT '修改时间',
   create_time  VARCHAR (14) COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

-- Add comments to the table 
ALTER TABLE huas_sessionid ADD CONSTRAINT HUAS_SESSION_KEY PRIMARY KEY (id);
COMMIT;
复制代码

三、需求实现

1、实现一个简单的登录

       利用Session进行登录,其实很简单,先校验完用户信息后将用户信息存Session,再是对用户的所有请求进行判断,看用户当前请求Session里有没有用户信息。

       如何对用户所有的请求进行拦截校验,有几种解决方案。

       一、是写一个BaseController,写一个对Session校验的方法,然后后面需要判断用户是否登录的Controller 都继承这个类,然后用这个方法在每个请求方法里进行手动校验,有一说一,非常不推荐,太繁琐冗余

复制代码
import javax.servlet.http.HttpServletRequest;

public class BaseController {

    protected boolean checkLogin(HttpServletRequest request) {
        System.out.println("==BaseController===checkLogin==");
        boolean flag= request.getSession().getAttribute("loginStatus")==null?false:(boolean)request.getSession().getAttribute("loginStatus");
        return flag;
        
    }
}
复制代码
复制代码
@Controller
@RequestMapping({"/login", "/"})
public class LoginController extends BaseController{
    @Autowired
    HttpServletRequest request;
    @Autowired
    LoginService loginService;

    @RequestMapping({"/index", "/"})
    public String index(){
        Boolean loginStatus=(Boolean) request.getSession().getAttribute("loginStatus");
        if(loginStatus!=null&&loginStatus) 
            return "home/index";
        return login();
    }
    
}
复制代码

  二、是写一个拦截器,对指定请求进行登录拦截,看当前请求有没有用户信息,有就放行,没有就转发到登录页面。

  1、MvcController 类 用户前端页面跳转

复制代码
package com.mangoubiubiu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/mvc")
public class MvcController {
    @GetMapping(value = "/index")
    public String index(HttpServletRequest request){
        return "/login";
    }
    
    @GetMapping(value = "/l/admin")
    public String admin(HttpServletRequest request){
        return "/admin";
    }
}
复制代码

  2、登录Controller 

复制代码
package com.mangoubiubiu.controller;


import com.mangoubiubiu.annotation.Auth;
import com.mangoubiubiu.entities.HuasUser;
import com.mangoubiubiu.event.SessionIdEvent;
import com.mangoubiubiu.exception.BusinessException;
import com.mangoubiubiu.exception.CommonErrorCode;
import com.mangoubiubiu.service.LoginService;
import com.mangoubiubiu.utils.R;
import com.mangoubiubiu.vo.UserLogin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;

@Api(tags = "登录模快")
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class LoginController {
    final ApplicationEventPublisher context;
    final LoginService loginService;

    @ApiImplicitParam(name = "userLogin",value = "用户信息",required = true)
    @ApiOperation(value = "登录接口")
    @PostMapping("/login")
    public R login(@RequestBody UserLogin userLogin){
        boolean flag = false;
        String type = userLogin.getType();
        if(StringUtils.isBlank(type)){
            throw  new BusinessException(CommonErrorCode.E_100101);
        }
        //账号密码登录
        if("0".equals(type)){
            flag= loginService.loginByPwd(userLogin);
        //验证码登录
        }else if("1".equals(type)){
            flag= loginService.loginByPhone(userLogin);

        }

        return flag==true?R.ok():R.error().message("登录失败");
   }
   
}
复制代码

  3、登录Service

复制代码
package com.mangoubiubiu.service.impl;

import com.mangoubiubiu.entities.HuasUser;
import com.mangoubiubiu.enums.SessionCodeEnum;
import com.mangoubiubiu.event.SessionIdEvent;
import com.mangoubiubiu.event.UserSingOutEvent;
import com.mangoubiubiu.exception.BusinessException;
import com.mangoubiubiu.exception.CommonErrorCode;
import com.mangoubiubiu.mapper.HuasUserMapper;
import com.mangoubiubiu.service.LoginService;
import com.mangoubiubiu.service.SessionService;
import com.mangoubiubiu.utils.PasswordUtil;
import com.mangoubiubiu.vo.UserLogin;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    final ApplicationEventPublisher context;

    final HuasUserMapper mapper;

    final SessionService sessionService;

    @Override
    public boolean loginByPwd(UserLogin userLogin) {
        String account = userLogin.getAccount();
        String pwd= userLogin.getPwd();
        if(StringUtils.isBlank(account) || StringUtils.isBlank(pwd)){
            throw new BusinessException(CommonErrorCode.E_100101);
        }
        HuasUser huasUser = mapper.selectByAccount(account);
        //用户不存在
        if(huasUser==null){
            throw new BusinessException(CommonErrorCode.U_900102);
        }
        System.out.println(huasUser.toString());
        //校验密码
        boolean verify = PasswordUtil.verify(pwd, huasUser.getPwd());
        if(!verify){
            throw new BusinessException(CommonErrorCode.U_900103);
        }
        //保存session
        sessionService.saveSession(huasUser);
        
        return true;
    }

    @Override
    public boolean loginByPhone(UserLogin userLogin) {
        return false;
    }

    
}
复制代码

  4、拦截器

复制代码
package com.mangoubiubiu.intercepter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mangoubiubiu.entities.HuasUser;
import com.mangoubiubiu.enums.SessionCodeEnum;
import com.mangoubiubiu.service.SessionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;



@Component
@RequiredArgsConstructor
public class LoginInterceptor implements HandlerInterceptor {

    final SessionService sessionService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HuasUser user=(HuasUser)request.getSession().getAttribute(SessionCodeEnum.USER_INFO.getKey());
        String servletPath = request.getServletPath();
        //如果当前请求页是登录页 跳转到首页
        if("/mvc/index".equals(servletPath) ){
            if (user!=null) {
                System.out.println("/mvc/index");
                request.getRequestDispatcher("/mvc/l/admin").forward(request, response);
            }
            return true;
        }
        //用户已登录
        if (user!=null) {
            //如果用户状态改变了 移除当前session
            if("1".equals(user.getUserLogFlag())){
                sessionService.removieSession();
            }
            //放行
            return true;
        }
        request.getRequestDispatcher("/mvc/index").forward(request, response);
        //重定向到登录页面
        return false;
    }
}
复制代码
复制代码
package com.mangoubiubiu.conf;

import com.mangoubiubiu.intercepter.LoginInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

   final   LoginInterceptor interceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,配置拦截地址
        registry.addInterceptor(interceptor).addPathPatterns("/mvc/**");
       // registry.addInterceptor(interceptor).addPathPatterns("/user/**");
    }

}
复制代码

 5、前端页面Ajax

复制代码
                      $.ajax({
                          type:"POST",
                          dataType: "json",
                          contentType:'application/json;charset=UTF-8',  //设置后
                          url:"/huas/user/login",
                          //指定
                          data: JSON.stringify(param),
                          //预期服务器返回的数据类型
                           //服务器响应成功时候的回调函数
                           success:function(result){
                                   if(result.code==20000){
                                     window.location = "/huas/mvc/l/admin";
                                 }else if(result.code== "900102"){
                                     $("#loginSpanTips").html( "*"+result.message+"!");
                                  }else if(result.code == "900103"){
                                     $("#pwdSpanTips").html( "*"+result.message+"!");
                                  }else{
                                     $("#loginSpanTips").html( "*未知错误");
                                 }

                                },error:function(xhr, textStatus, err){//服务器响应失败时候的回调函数

                           }

                       })
复制代码

四、测试 此页面为毕业设计页面。。。。。

 

 

 

 

查到校验存 Session   成功

 

本文作者:KwFruit

本文链接:https://www.cnblogs.com/mangoubiubiu/p/16102552.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   KwFruit  阅读(194)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起