Springboot设置session

3 篇文章 0 订阅
1 篇文章 0 订阅

参考他人的(老版本)
https://blog.csdn.net/xjj1040249553/article/details/82658889

注意1:配置文件新版本更改:
https://blog.csdn.net/qq_33326449/article/details/80457571

json导入使用
https://blog.csdn.net/sinat_35821285/article/details/79762464

spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0

redis的使用(中文官网)
http://www.redis.cn/commands.html#list

学习参考视频()
https://www.bilibili.com/video/av38657363?p=82

1.安装与开启

已经安装好了
F:\Redis-x64-3.0.504

1.1
开启服务:redis-server.exe redis.windows.conf

在这里插入图片描述

F:\Redis-x64-3.0.504>redis-server.exe redis.windows.conf

1.2 建立连接(可选,测试一下)

redis-cli.exe -h 127.0.0.1 -p 6379

在这里插入图片描述

2.引入starter

<!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

3.配置redis

#springboot配置文件 建立连接
spring.redis.host=localhost

4.springboot test使用

4.1配置类

@Configuration
public class MyRedisConfig {
    @Bean
    public RedisTemplate<Object, Manager> managerRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Manager> template = new RedisTemplate<Object, Manager>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Manager> ser=new Jackson2JsonRedisSerializer<Manager>(Manager.class);
        template.setDefaultSerializer(ser);
        return template;
    }
}

4.2测试中使用

    @Autowired
    StringRedisTemplate stringRedisTemplate;//专门抽出来操作k-v都是字符串的

    /**
     * redis常用五大数据类型
     * String() list(列表) Set(集合) Hash(散列) ZSet(有序集合)
     *         stringRedisTemplate.opsForValue();  String
     *         stringRedisTemplate.opsForList();   list
     *         stringRedisTemplate.opsForSet();   Set
     *         stringRedisTemplate.opsForHash();  Hash
     *         stringRedisTemplate.opsForZSet();  ZSet
     */
    @Test
    public void test01() {
        stringRedisTemplate.opsForValue().append("msg", "hello");
        String s=stringRedisTemplate.opsForValue().get("msg");
        System.out.println(s);

        stringRedisTemplate.opsForList().leftPush("mylist", "1");
        stringRedisTemplate.opsForList().leftPush("mylist", "2");
    }
    @Autowired
    LoginMapper loginMapper;

    @Autowired
    RedisTemplate<Object,Manager> managerRedisTemplate;//k-v都是对象的

    //测试保存对象,需要配置,配置代码为:类MyRedisConfig
    @Test
    public void test02() {
        //有要求Manager是可序列化的
        Manager manager=loginMapper.getManagerByPasswordAndPhone("15990011043","034676");
        //1.将数据以json的方式保存
        //(方式1)自己将对象转化为json
        //(方式2)redisTemplate默认的序列化规则
//选择方式二
        managerRedisTemplate.opsForValue().set("man-01", manager);
        manager =managerRedisTemplate.opsForValue().get("man-01");

        System.out.println( manager.getPhone());
    }

5.配置拦截器

5.1编写登录状态拦截器RedisSessionInterceptor

所有请求经过这个拦截器,除了登录请求

public class RedisSessionInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //Object user=request.getSession().getAttribute("loginUser");
        //无论访问的地址是不是正确的,都进行登录验证,登录成功后的访问再进行分发,404的访问自然会进入到错误控制器中
        HttpSession session = request.getSession();
        if(session.getAttribute("phone")!=null){
            try
            {
                //验证当前请求的session是否是已登录的session
                String loginSessionId = redisTemplate.opsForValue().get("loginUser:" + (String) session.getAttribute(
                        "phone"));//收到的是电话号码的字符串,例如"15990011043"
                if (loginSessionId != null && loginSessionId.equals(session.getId()))
                {
                    //已登录,放行请求
                    return true;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

        }
        //未登录
        response401(response);

//        request.setAttribute("msg", "没有权限请先登录");
//        request.getRequestDispatcher("/index.html").forward(request,response );
        return false;

    }
    private void response401(HttpServletResponse response)
    {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        try
        {
            response.getWriter().print(JSON.toJSONString(new ReturnData(StatusCode.NEED_LOGIN, "", "用户未登录!")));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

}

5.2编写拦截器WebSecurityConfig

@Configuration
public class WebSecurityConfig extends WebMvcConfigurationSupport {
    @Bean
    public RedisSessionInterceptor getSessionInterceptor(){
        return new RedisSessionInterceptor();
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        //所有已api开头的访问都要进入RedisSessionInterceptor拦截器进行登录验证,并排除login接口(全路径)。必须写成链式,分别设置的话会创建多个拦截器。
        //必须写成getSessionInterceptor(),否则SessionInterceptor中的@Autowired会无效
        registry.addInterceptor(getSessionInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/manager" +
                "/login");
        super.addInterceptors(registry);

    }
}

6.接收请求

@RestController
@RequestMapping(value = "/api/manager")
public class ManagerLoginController {

    @Autowired
    LoginMapper loginMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    Logger logger= LoggerFactory.getLogger(getClass());

    @PostMapping("/login" )
    public ReturnData loginManager(
            HttpServletRequest request,
            @RequestParam(value = "phone") String phone,
            @RequestParam(value = "password") String password
    ){

        logger.trace("后台接收到登录请求");
        logger.trace("phone:"+phone);
        logger.trace("password:"+password);

        Manager manager=loginMapper.getManagerByPasswordAndPhone(phone,password);

        if(manager!=null){
            HttpSession session=request.getSession();
            //session中存放电话号码
            session.setAttribute("loginUserPhone",manager.getPhone());
            //redis中存值,key:"loginUser:15990011043" value:"56D2E8E078473B331A2BBF0A83A5DD68"  即session的id
            redisTemplate.opsForValue().set("loginUser:" + manager.getPhone(), session.getId());
            return new ReturnData(StatusCode.REQUEST_SUCCESS, manager,"登录成功!");
        }else{
            return new ReturnData(StatusCode.ACCOUNT_OR_PASSWORD_ERROR,"" ,"账户名或密码错误!");
        }

    }
    @PostMapping("/logout" )
    public ReturnData loginManager(HttpServletRequest request){
        logger.trace("后台接收到退出登录请求");

        HttpSession session=request.getSession();
        //获取session中的电话号码
        String phone=(String)session.getAttribute("loginUserPhone");
        logger.trace("获取session中的电话号码:"+phone);
        //删除session
        session.invalidate();
        logger.trace("删除session");
        //删除redis的session Id
        redisTemplate.delete("loginUser:" +phone);
        logger.trace("删除redisTemplate:"+"loginUser:" +phone);
        logger.trace("删除成功");
        return new ReturnData(StatusCode.REQUEST_SUCCESS,"","退出成功!");
    }
}

7.遇到的问题

7.1跨域问题:

具体配置参考文章开头的链接

@Configuration
public class CORSConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//配置可以被跨域的路径
                .allowedMethods("*")//allowedMethods:允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等。
                .allowedOrigins("http://localhost:8080")//允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:"http://www.baidu
                // .com",只有百度可以访问我们的跨域资源。
                .allowCredentials(true)
                .allowedHeaders("*");//允许所有的请求header访问,可以自定义设置任意请求头信息,如:"X-YAUTH-TOKEN"
    }
}

7.2session丢失

是因为前端使用了axios,axio

1.Vue的main.js添加:

Axios.defaults.withCredentials = true

2.springboot配置添加:

 .allowedOrigins("http://localhost:8080")
.allowCredentials(true)

必须指明来源是http://localhost:8080

8.总结

总体流程就是前端发送axios请求,springboot的WebSecurityConfig(规范)进行拦截,拦截的要求在RedisSessionInterceptor里,含有session且排除必要的请求后放行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值