spring boot 拦截器获取controller返回的数据_spring session 结合拦截器实战

本文介绍如何在Spring Boot中结合Spring Session和拦截器实现登录验证。通过示例展示从登录设置session信息,到拦截器校验,再到登出清空session的完整流程。同时探讨了Spring Session的优雅使用方式及其在实际应用中的配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景

前面我们学习了springboot整合redis实现分布式session,对 spring session 有了一个最基本的认识。

有时候我们希望登陆的时候设置对应的 session 信息,然后结合拦截器进行是否登陆校验。

本文就给出一个结合拦截器使用的例子,让我们进一步感受下 spring session 的魅力吧。

82b58ea3608891409b4344956750a054.png

实战

maven 依赖

    org.springframework.boot    spring-boot-starter-parent    1.5.9.RELEASE            org.springframework.session        spring-session                org.springframework.boot        spring-boot-starter-web                org.springframework.boot        spring-boot-starter-data-redis    

类结构

│  Application.java│├─config│      WebConfig.java│├─controller│      ExampleController.java│      UserController.java│├─interceptor│      SessionInterceptor.java│└─util        SessionUtil.java

基本方法

  • Application.java
package com.github.houbb.spring.session.learn.boot.redis;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;/** * @author binbin.hou * @since 1.0.0 */@SpringBootApplication@EnableRedisHttpSessionpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}

通过 @EnableRedisHttpSession 注解启用 redis http session 的功能。

ExampleController.java 类和入门案例中一样,此处不再赘述。

  • SessionUtil.java

一个 session 构建的基础工具类。

package com.github.houbb.spring.session.learn.boot.redis.util;/** * @author binbin.hou * @since 1.0.0 */public final class SessionUtil {    private SessionUtil(){}    /**     * session key 前缀     */    private static final String SESSION_KEY_PREFIX = "SESSION-KEY-";    public static String buildSessionKey(final String sessionId) {        return SESSION_KEY_PREFIX + sessionId;    }}

UserController.java

这里我们主要模拟一下用户的登陆和登出。

package com.github.houbb.spring.session.learn.boot.redis.controller;import com.github.houbb.spring.session.learn.boot.redis.util.SessionUtil;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;import java.util.UUID;@RestController@RequestMappingpublic class UserController {    @RequestMapping("/loginIndex")    public String loginIndex(HttpServletRequest req) {        return "http://localhost:8080/login?username=guest";    }    @RequestMapping("/login")    public String login(HttpServletRequest req) {        //1. 获取用户名密码        final String username = req.getParameter("username");        //2. 登陆校验        if("guest".equals(username)) {            //3. 设置对应的信息            String sessionId = UUID.randomUUID().toString();            String sessionKey = SessionUtil.buildSessionKey(sessionId);            // value 可以设置对应的权限值等等            String value = username;            req.getSession().setAttribute(sessionKey, value);            // 将 token 返回给前端            // 可以设置再页面的隐藏域中            return "sessionId: " + sessionId;        }        return "login failed";    }    @RequestMapping("/logout")    public String logout(HttpServletRequest req) {        String sessionId = req.getParameter("sessionId");        req.getSession().removeAttribute(SessionUtil.buildSessionKey(sessionId));        return "登出成功";    }}

登陆首页

loginIndex 为登陆的首页,为了简单,我们直接显示需要请求的地址即可:

http://localhost:8080/login?username=guest

登陆

校验对应的 username,并且设置对应的 session 信息。

并且将这个 token 返回给前端,用户在登出的时候需要指定这个 token 做校验。

登出

清空对应的 session 信息。

拦截器

SessionInterceptor.java

这里我们是通过对应的 token 获取。

当然,对于 spring session 也可以直接根据 JSESSIONID 这种更加优雅的方式设置和获取。

如果信息不存在,则直接返回到登陆页面。

package com.github.houbb.spring.session.learn.boot.redis.interceptor;import com.github.houbb.spring.session.learn.boot.redis.util.SessionUtil;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.Writer;/** * @author binbin.hou * @since 1.0.0 */@Componentpublic class SessionInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {        String sessionId = httpServletRequest.getParameter("sessionId");        if(StringUtils.isEmpty(sessionId)) {            handleForbidden(httpServletRequest, httpServletResponse, "请重新登陆");            return false;        }        // 获取登陆信息        String sessionKey = SessionUtil.buildSessionKey(sessionId);        String username = (String) httpServletRequest.getSession().getAttribute(sessionKey);        if(StringUtils.isEmpty(username)) {            handleForbidden(httpServletRequest, httpServletResponse, "请重新登陆");            return false;        }        return true;    }    @Override    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {    }    @Override    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {    }    private void handleForbidden(HttpServletRequest request, HttpServletResponse response, String info){        // 有这个值是异步请求,没有是同步请求。        String xRequest = request.getHeader("X-Requested-With");        if(!StringUtils.isEmpty(xRequest)){            //异步处理            response.setCharacterEncoding("UTF-8");            try {                Writer writer = response.getWriter();                writer.write(info);                response.setStatus(403);            } catch (IOException e) {                e.printStackTrace();            }        }else{            try {                // 可以跳转到登陆页面                request.getRequestDispatcher("loginIndex")                        .forward(request, response);            } catch (ServletException | IOException e) {                e.printStackTrace();            }        }    }}

拦截器设置

我们定义了拦截器,当然需要指定对应的生效范围:

package com.github.houbb.spring.session.learn.boot.redis.config;import com.github.houbb.spring.session.learn.boot.redis.interceptor.SessionInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.web.filter.CharacterEncodingFilter;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;/** * @author binbin.hou * @since 1.0.0 */@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter {    @Autowired    private SessionInterceptor sessionInterceptor;    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(sessionInterceptor)                .addPathPatterns("/**")                .excludePathPatterns("/loginIndex")                .excludePathPatterns("/login");    }    @Bean    public CharacterEncodingFilter initializeCharacterEncodingFilter() {        CharacterEncodingFilter filter = new CharacterEncodingFilter();        filter.setEncoding("UTF-8");        filter.setForceEncoding(true);        return filter;    }    @Override    public void addViewControllers(ViewControllerRegistry registry) {        registry.addViewController("/").setViewName("forward:/loginIndex");        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);        super.addViewControllers(registry);    }}

我们排除 /loginIndex 和 /login 这两个请求地址的 session 拦截校验,当然也可以根据实际情况排除静态文件。

registry.addViewController("/").setViewName("forward:/loginIndex"); 这句话可以将默认的首页重定向到登陆页面。

测试验证

首页

浏览器访问 http://localhost:8080/

页面显示:

http://localhost:8080/login?username=guest

登陆

我们直接输入 http://localhost:8080/login?username=guest

页面返回对应的 token:

sessionId: 5251161a-d946-41e5-98fc-eae2e5c01960

登出

我们登出的时候,带上这个参数:http://localhost:8080/logout?sessionId=5251161a-d946-41e5-98fc-eae2e5c01960

页面提示:

登出成功

如果我们再次请求,页面就会跳转到登陆首页,因为这个时候的 session 已经被清空了。

小结

这一节我们展示了如何结合拦截器使用 spring session,这也是目前比较主流的做法。

对于很多讲解到这里一般就结束了,不过老马实际上是为了引入接下来的内容。

spring session 底层的实现原理是怎样的?

下一节将和各位小伙伴们一起学习下 spring session 的源码。

希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。

我是老马,期待与你的下次相遇。

46b14a9b1d94ab04db23eb72be20e494.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值