Realice el intercambio de sesiones de front-end y back-end

Tabla de contenido

1. Cómo implementar el intercambio de sesiones

1.1 Modificar la clase de configuración de Shiro

2. Resuelva el problema del front-end que no admite cookies.

2.1 Modificar la interfaz de inicio de sesión

2.2 Modificar el método de inicio de sesión del front-end

2.3 Modificar el archivo main.js del front-end

2.4 Método para anular DefaultWebSessionManager

2.5 Modificar la clase de configuración de shiro

2.6 Modificar el filtro shiroFilter

1. Cómo implementar el intercambio de sesiones

De forma predeterminada, las sesiones se almacenan en la memoria de sus respectivos servicios. Podemos resolver el problema de no compartir permitiendo que las sesiones se almacenen de manera uniforme en redis.

Dependencia loca del pastel. --- Proporciona una clase para que redis almacene sesiones.

1.1 Modificar la clase de configuración de Shiro

@Bean
    public DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        //设置缓存管理器
        securityManager.setCacheManager(redisCacheManager());
        //session管理
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }
    
    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(sessionDAO());//sessionDao用于操作session对象,在容器中对对象session进行CRUD操作
        return sessionManager;
    }

    @Bean
    public SessionDAO sessionDAO(){
        //该类会对对象session进行CRUD操作
        RedisSessionDAO sessionDAO = new RedisSessionDAO();
        sessionDAO.setRedisManager(redisManager());
        return sessionDAO;
    }

    //redis缓存管理器
    @Bean
    public RedisCacheManager redisCacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        //redisCacheManager.setPrincipalIdFieldName("userId");
        return redisCacheManager;
    }

    //redis管理器
    @Bean
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setHost("192.168.232.166"+":6379");
        redisManager.setDatabase(1);
        return redisManager;
    }

    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm=new MyRealm();
        //设置密码加密器
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return myRealm;
    }

   @Bean
    public HashedCredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(5);
        return credentialsMatcher;
    }

2. Resuelva el problema del front-end que no admite cookies.

Motivo: el DefaultWebSessionManager predeterminado solo acepta el JsessionId almacenado en Cookie. La consulta encontró que la clave correspondiente no existe en redis.

Cuando el cliente envía una solicitud, lleva el sessionId en el encabezado de la solicitud y luego anula el método getSessionId() en DefaultWebSessionManager.

resolver:

1. Coloque el ID de sesión en el encabezado de la solicitud.

2. Anule el método getSessionId para obtener el ID de sesión en el encabezado de la solicitud.

2.1 Modificar la interfaz de inicio de sesión

package com.lx.controller;

import com.lx.vo.LoginVo;
import com.lx.vo.Result;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * @program: springboot-shiro
 * @description:前后端分离
 * @author: 
 * @create: 2023-07-10 16:51
 **/
@Controller
/*@CrossOrigin
 origins:允许哪些跨域访问该接口 allowedHeaders:允许携带哪些头信息的请求访问 methods:允许哪些请求方式跨域请求接口*/
public class LoginPlusController {

    @PostMapping("/loginPlus")
    @ResponseBody
    public Result login(@RequestBody LoginVo loginVo) {
        System.out.println(loginVo);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUsername(), loginVo.getPassword());
        try {
            subject.login(token);
            return new Result(200,"登录成功",subject.getSession().getId());//携带当前会话的id
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(500,"账号或密码错误",null);
        }
    }
}

2.2 Modificar el método de inicio de sesión del front-end

 methods:{
    submitForm(){
      console.log(this.form)
      this.$http.post("http://localhost:8080/loginPlus",this.loginForm).then(result=>{
        if (result.data.code==200){
          this.$message.success("登录成功")
          sessionStorage.setItem("token",result.data.data())//存在sessionStorage中,浏览器关闭token就销毁了
          this.$router.push("/product")//路由跳转
        }else {
          this.$message.error("账号或密码错误")
        }
        console.log(result)
      })
    }

2.3 Modificar el archivo main.js del front-end

//设置axios的请求拦截器
axios.interceptors.request.use(config=>{
  //从sessionStorage中获取token值
  var item = sessionStorage.getItem("token");
  if (item){
    config.headers.token=item;
  }
  return config;
})

2.4 Método para anular DefaultWebSessionManager

package com.lx.realm;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;

/**
 * @program: springboot-shiro
 * @description:
 * @author: 
 * @create: 2023-07-11 15:08
 **/
public class MyWebSessionManager extends DefaultWebSessionManager {
    private static final String AUTHORIZATION = "token";
    private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        //获取请求头中名称为token的内容
        String id = WebUtils.toHttp(request).getHeader("token");
        if (!StringUtils.isEmpty(id)) { //如果存在该token
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "Stateless request");
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return id;
        } else {
            //从cookie中获取sessionId.
            return super.getSessionId(request, response);
        }
    }
}

2.5 Modificar la clase de configuración de shiro

@Bean
    public SessionManager sessionManager(){
        //DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        MyWebSessionManager sessionManager = new MyWebSessionManager();//修改为我们自己定义的SessionManager类
        sessionManager.setSessionDAO(sessionDAO());//sessionDao用于操作session对象,在容器中对对象session进行CRUD操作
        return sessionManager;
    }

2.6 Modificar el filtro shiroFilter

Descubrimos que para solicitudes entre dominios, se enviarán dos solicitudes: la primera solicitud de OPCIONES y la segunda solicitud es la solicitud real.

Solicitud de OPCIONES: vanguardia.

Entonces todos permitimos solicitudes de OPCIONES.

package com.lx.filter;

import com.alibaba.fastjson.JSON;
import com.lx.vo.Result;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;

/**
 * @program: springboot-shiro
 * @description:
 * @author: 
 * @create: 2023-07-11 16:48
 **/
public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        response.setContentType("appliation/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        Result result = new Result(401, "未登录", null);
        String jsonString = JSON.toJSONString(result);
        writer.print(jsonString);
        writer.flush();
        writer.close();
        return false;
    }


    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        HttpServletRequest request1 = (HttpServletRequest) request;
        //获取请求方式
        String method = request1.getMethod();
        if ("OPTIONS".equals(method)){
            return true;
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }
}

Supongo que te gusta

Origin blog.csdn.net/weixin_54065960/article/details/131659144
Recomendado
Clasificación