redis 登录_实战开发,使用 Spring Session 完成网站登录改造

news/2024/5/14 2:40:23/文章来源:https://blog.csdn.net/weixin_39589644/article/details/110511156

上次小黑在文章中介绍了四种分布式一致性 Session 的实现方式,在这四种中最常用的就是后端集中存储方案,这样即使 web 应用重启或者扩容,Session 都没有丢失的风险。

725d470e9fc94183b2b75b6aa2ff184b

今天我们就使用这种方式对 Session 存储方式进行改造,将其统一存储到 Redis 中。

实现方案

我们先来想一下,如果我们不依靠任何框架,自己如何实现后端 Session 集中存储。

这里我们假设我们的网站除了某些页面,比如首页可以直接访问以外,其他任何页面都需要登录之后才能访问。

如果需要实现这个需求,这就需要我们对每个请求都进行鉴权,鉴权目的是为了判断用户是否登录,判断用户角色。

如果用户没有登录,我们需要将请求强制跳转到登录页面进行登录。

用户登录之后,我们需要将登录获取到的用户信息存储到 Session 中,这样后面请求鉴权只需要判断 Session 中是否存在即可。

知道整个流程之后,其实实现原理就不是很难了。

我们可以使用类似 AOP 的原理,在每个请求进来之后,都先判断 Session 中是否存在用户信息,如果不存在就跳转到登录页。

整个流程如下所示:

a1c8e325b6e348b68e37423f35647ec8

我们可以利用 Servelt Filter 实现上述流程,不过上述整套流程,Spring 已经帮我们实现了,那我们就不用重复造轮子了。

我们可以使用 Spring-SessionSpring-security 实现上述网站的流程。

Spring-Session 是 Spring 提供一套管理用户 Session 的实现方案,使用 Spring-Session 之后,默认 WEB 容器,比如 Tomcat,产生的 Session 将会被 Spring-Session 接管。

除此之外,Spring-Session 还提供几种常见后端存储实现方案,比如 Redis,数据库等。

有了 Spring-Session 之后,它只是帮我们解决了 Session 后端集中存储。但是上述流程中我们还需要登录授权,而这一块我们可以使用 Spring-security 来实现。

Spring-security 可以维护统一的登录授权方式,同时它可以结合 Spring-Session 一起使用。用户登录授权之后,获取的用户信息可以自动存储到 Spring-Session 中。

好了,不说废话了,我们来看下实现代码。

下述使用 Spring Boot 实现, Spring-Boot 版本为:2.3.2.RELEASE

Spring Session

首先我们引入 Spring Session 依赖,这里我们使用 Redis 集中存储 Session 信息,所以我们需要下述依赖即可。

    org.springframework.session    spring-session-data-redis

如果不是 Spring Boot 项目,那主要需要引入如下依赖:

  org.springframework.data  spring-data-redis  2.3.0.RELEASE  org.springframework.session  spring-session-core  2.3.0.RELEASE

引入依赖之后,我们首先需要在 application.properties增加 Session 相关的配置:

## Session 存储方式spring.session.store-type=redis## Session 过期时间,默认单位为 sserver.servlet.session.timeout=600## Session 存储到 Redis 键的前缀spring.session.redis.namespace=test:spring:session## Redis 相关配置spring.redis.host=127.0.0.1spring.redis.password=****spring.redis.port=6379

配置完成之后,Spring Session 就会开始管理 Session 信息,下面我们来测试一下:

@ResponseBody@GetMapping("/hello")public String hello() {    return "Hello World";}

当我们访问上面地址之后,访问 Redis ,可以看到存储的 Session 信息。

推荐大家一个 Redis 客户端「Another Redis DeskTop Manager」,这个客户端 UI 页面非常漂亮,操作也很方便,下载地址:

https://github.com/qishibo/anotherredisdesktopmanager/releases

791cb957004842d19567d898839381cf

默认情况下,Session 默认使用HttpSession 序列化方式,这种值看起来不够直观。我们可以将其修改成 json 序列化方式,存储到 redis 中。

@Configurationpublic class HttpSessionConfig implements BeanClassLoaderAware {    private ClassLoader loader;    @Bean    public RedisSerializer springSessionDefaultRedisSerializer() {        return new GenericJackson2JsonRedisSerializer(objectMapper());    }    /**     * Customized {@link ObjectMapper} to add mix-in for class that doesn't have default     * constructors     *     * @return the {@link ObjectMapper} to use     */    private ObjectMapper objectMapper() {        ObjectMapper mapper = new ObjectMapper();        mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));        return mapper;    }    @Override    public void setBeanClassLoader(ClassLoader classLoader) {        this.loader = classLoader;    }}

修改之后 Redis 键值如下所示:

77c00d7f8619411792e7de3936d598a2

ps:这里 Redis 键值含义,下次分析源码的时候,再做分析。

Spring Session 还存在一个 @EnableRedisHttpSession,我们可以在这个注解上配置 Spring Session 相关配置。

@EnableRedisHttpSession(redisNamespace = "test:session")

需要注意的是,如果使用这个注解,将会导致 application.properties Session 相关配置失效,也就是说 Spring Session 将会直接使用注解上的配置。

eee041e40479448eb5b4f1b1a9f37d59

这里小黑比较推荐大家使用配置文件的方式。

好了,Spring Session 到这里我们就接入完成了。

Spring security

上面我们集成了 Spring Session,完成 Session 统一 Redis 存储。接下来主要需要实现请求的登陆鉴权。

这一步我们使用 Spring security 实现统一的登陆鉴权服务,同样的框架的还有 Shiro,这里我们就使用 Spring 全家桶。

首先我们需要依赖的相应的依赖:

    org.springframework.boot    spring-boot-starter-security

引入上面的依赖之后,应用启动之后将会生成一个随机密码,然后所有的请求将会跳转到一个 Spring security 的页面。

e4cf480f98cc440da4f6c168b1625123

默认密码

f2c9ccef9a454128a3d7d431102aa183

登录页面

这里我们需要实现自己业务的登陆页,所以我们需要自定义登录校验逻辑。

在 Spring security 我们只需要实现 UserDetailsService接口,重写 loadUserByUsername方法逻辑。

@Servicepublic class UserServiceImpl implements UserDetailsService {    @Autowired    PasswordEncoder passwordEncoder;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        // 简单起见,直接内部校验        String uname = "admin";        String passwd = "1234qwer";        // 如果是正式项目,我们需要从数据库数据数据,然后再校验,形式如下:        // User user = userDAO.query(username);        if (!username.equals(uname)) {            throw new UsernameNotFoundException(username);        }        // 封装成 Spring security 定义的 User 对象        return User.builder()                .username(username)                .passwordEncoder(s -> passwordEncoder.encode(passwd))                .authorities(new SimpleGrantedAuthority("user"))                .build();    }}

上面代码实现,这里主要在内存固定用户名与密码,真实环境下,我们需要修改成从数据库查询用户信息。

接着我们需要把 UserServiceImpl 配置到 Spring security 中。

@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired    UserServiceImpl userService;    @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }    /**     * 使用自定义用户服务校验登录信息     *     * @param auth     * @throws Exception     */    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        // 用户登录信息校验使用自定义 userService        // 还需要注意密码加密与验证需要使用同一种方式        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());    }}

上面的配置中,密码部分我们使用 BCrypt 算法加密,这里需要注意,加密与解密需要使用同一种方式。

接着我们需要实现一个自定义的登陆页面,这里就懒得自己写了,直接使用 spring-session-data-redis 页面。

html>    Login
                            Please Login -            
Invalid username and password.
            
You have been logged out.
            Username                        Password                                    remember me:                         
                Log in            
            

这里需要注意一点,这里 form 表单的请求地址使用 /auth/login,我们需要在下面配置中修改,默认情况下登录请求的地址需要为 /login。

接着我们在上面的 SecurityConfig 类增加相应配置方法:

/** * 自定义处理登录处理 * * @param http * @throws Exception */@Overrideprotected void configure(HttpSecurity http) throws Exception {    http.authorizeRequests((authorize) -> authorize            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // 静态资源,比如 css,js 无需登录鉴权            .anyRequest().permitAll() // 其他页面需要登录鉴权    ).formLogin((formLogin) -> formLogin  // 自定义登录页面            .loginPage("/login") // 登录页            .loginProcessingUrl("/auth/login") // 自定义登录请求地址            .permitAll()// 登录页当然无需鉴权了,不然不就套娃了吗?    ).logout(LogoutConfigurer::permitAll // 登出页面    ).rememberMe(rememberMe -> rememberMe            .rememberMeCookieName("test-remember") // 自定义记住我 cookie 名            .key("test") // 盐值            .tokenValiditySeconds(3600 * 12)) // 记住我,本地生成 cookie 包含用户信息    ;}

这个方法可能比较长,重点解释一下:

  • authorizeRequests方法内需要指定那些页面需要鉴权,这里我们指定静态资源无需登录鉴权,其他请求我们都需要登录鉴权
  • formLogin 方法内修改默认的登录页面地址,以及登录的请求地址。
  • logout在这里面可以配置登出的相关配置。
  • rememberMe开启这个功能之后,当内部 Session 过期之后,用户还可以根据用户浏览器中的 Cookie 信息实现免登录的功能。

最后我们需要配置一些页面的跳转地址:

@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        // 首页        registry.addViewController("/").setViewName("home");        // 登录之后跳转到 home 页        registry.addViewController("/login").setViewName("login");    }}

总结

到此为止,我们已经集成 Spring-SessionSpring-security 完成完整的网站的登录鉴权功能。从这个例子可以看到,引入这个两个框架之后,我们只需要按照 Spring 规范开发即可,其他复杂实现原理我们都不需要自己实现了,这样真的很方便。

上面只是一个简单的小例子,小黑只是抛转引玉一下,真实开发中可能需要修改配置会更多,这里需要使用小伙伴自己在深入研究了。

参考

  1. https://creaink.github.io/post/Backend/SpringBoot/Spring-boot-security.html
  2. https://github.com/spring-projects/spring-session

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_750390.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html5实战开发视频,HTMl5网站开发项目实战视频教程

本课程是继HTML5新手入门之后的实战进阶教程,依然是由著名讲师李炎恢老师精心讲解的,本教程用各种实例来为大家讲解HTML5在PC端的固定布局,在移动端的流体布局,以及响应式布局的布局方法,通过多种HTML5布局方法的学习&…

php伪静态网站,php怎么实现网页伪静态

php实现网页伪静态的方法:首先在服务器根目录创建一个“.htaccess”文件;然后添加内容为“RewriteRule ^index-(\d)\.html$ index.php?id$1”即可。本文操作环境:Windows7系统、PHP7.1版,DELL G3电脑.htaccess实现php网站伪静态&…

jitter 如何优化网络_海盈宝典 网络推广如何做好网站SEO优化

网站整站优化是网络推广中做好 SEO的一项重要工作,如何做好 SEO优化?如何做好网站 SEO优化网络推广。一、定位网站关键词搜索引擎优化给网站一开始做优化时,不会马上设置关键词,而是首先分析网站主要是做什么产品/服务。了解网站的…

R语言元胞自动机单车道代码_工具篇|神器一出,作图无忧:一个完爆R语言的作图网站...

同学A:哎,数据分析了好久终于有点眉目了,可是这R语言作图实在是令我头秃呀,一串串的代码,搞得我头昏眼花的,心塞塞~同学B:哈哈哈,不瞒你说,我刚刚发现了一个万能的作图网…

php网站制作成品,PHPweb成品网站修改方法

PHPweb成品网站修改方法(2013-01-04 20:52:04)标签:杂谈分类:网页PHPweb虽然说是智能的,但是由于聚合的比较杂乱,修改起来不是很方便。现在总结一下PHPweb成品网站修改方法:(1)网站右上角联系我们,邮箱等修改路径&…

Linux网站组目录环境命令,Linux初级命令

cd命令cd切换目录:cd 目标目录当前目录:. 上一级目录:.. 返回家目录:cd ~/cd 空格切换到上次所在目录:cd -打印当前用户名字:whomi打印当前用户的用户编号和用户组编号:id打印当前用户家目录&am…

大数据监测网站模板

图示: 演示地址: http://www.bootstrapmb.com/item/4232/preview 这个网站有一大波模板 http://www.bootstrapmb.com/

锚链接点击添加class_用内部链接提升网站收录的技巧分享

大家都知道,增加网站的权重可以增加外部链接,其实优化内部链接还可以帮助提高SEO效果。内部链接主要是在同一个网站上,内容页面相互链接。图片源自网络下面和大家分享如何用内部链接提升网站收录:1.页面链接指向首页在网站多个页面…

如何将网站进行服务器端加密,如何将Zoom Web Client SDK和你的网站整合?

之前我们演示过“如何使用DRM-X4.0保护Zoom Web SDK(防止Zoom会议屏幕录像)”,在这里我们将演示“如何将Zoom Web Client SDK和你的网站进行整合”。修改后的Zoom SDK加入会议的效果如下:用户登录你的网站,通过访问指定的PHP页面,…

网站开发需要哪些技术_网站开发的过程中需要注意哪些问题?

随着互联网的快速发展,网站建设技术方面也不断进步,最初设计制作一个网站需要的时间很长,费用也很高。现在,随着建站系统的出现,节省了网站开发时间,成本。制作一个网站往往只需要设计前端即可,…

mount nfs 密码_IT运维实战篇:NFS+Keepalived高可用集群部署discuz论坛网站

NFS(Network File System)是一个网络文件系统,是Linux系统直接支持文件共享的一直文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访…

5 python 页面说明_PDF 的各种操作,我用 Python 来实现(附网站和操作指导)

导言PDF 处理是日常工作中的常见需求,包括 PDF 合并、删除、提取等。更复杂的任务如:将 PDF 转换成 图像。下面通过几个简单的例子和一份代码,帮助大家解决上面的需求,操作非常简单。在文末我会提供一份源码和一个神奇的 PDF 处理…

php源码仿三一重工,织梦仿三一重工大气企业网站PHP源码

模板介绍源码名称:仿三一重工大气企业网站PHP源码模仿三一重工企业网站PHP源码,测试是完整和无错的,与主流浏览器兼容。模板包含安装说明和测试数据。这个模板是基于DEDE的CMS 5.7GBK设计的。如果需要UTF-8版本,请自己转换。模板的…

我的世界服务器linux网站,Ubuntu架设Minecraft服务器

Minecraft是非常流行的沙盒游戏,为了和几个朋友一起玩这个游戏,我需要一个属于自己的虚拟世界,自己的Minecraft服务器。我在DigitalOcean的vps上架设Minecraft服务器,如果你只需在局域网内游戏,使用本地主机即可。下面…

在阿里云部署 Hexo 网站

一开始自己的网站 leehao.me 托管在 GitHub 上面,考虑到 GitHub 的访问可能不稳定,另外,也是抱着学习的目的,就将网站迁移到阿里云上面来了。 网站的总体结构如下图所示: 域名 leehao.me 指向负载均衡 SLB&#xff08…

Hexo 网站配置免费阿里云证书

原来的个人网站 leehao.me 使用了阿里云的负载均衡服务,因此 HTTPS 证书也是部署在负载均衡服务器上。文章《在阿里云部署 Hexo 网站》介绍了采用负载均衡方式来部署网站的方法。 考虑到网站访问流量不高且为了减少费用,决定不再使用负载均衡服务&#…

Hexo 网站支持 HTTP/2

HTTP/2 具有以下的特性: 采用二进制传输数据基于流的多路复用头部压缩服务端推送 由于 HTTP/2 可以提升网站访问速度,因此,本人决定对个人站点 Leo 的博客 进行 HTTP/2 升级改造。 leehao.me 网站采用 Ngninx Hexo NexT 实现&#xff0c…

php网站设置不可复制,css如何实现禁止文本被选中,禁止复制?(代码示例)

在前端开发中,有时会出现这样一种情况:双击文字后,文字就会被选中,特别丑,一点也不美观,也很不方便;而且有时候在某些网页模块上我们就是就是需要文字不可以被选中或复制。那么如何实现这种需求…

拔错电源,导致网站宕机 24 小时

黑客技术点击右侧关注,了解黑客的世界!推荐↓↓↓ 长按关注?【16个技术公众号】都在这里!涵盖:程序员大咖、源码共读、程序员共读、数据结构与算法、黑客技术和网络安全、大数据科技、编程前端、Java、Python、Web编程开发、Andr…

某程序员上线原谅宝:抓取全球不可描述网站和社交平台10万渣女

黑客技术点击右侧关注,了解黑客的世界!Linux编程点击右侧关注,免费入门到精通!程序员严选甄选正品好物,程序员生活指南!来源丨工程狮一图https://www.jianshu.com/p/29a69e0ad28b 要想生活过得去&#xf…