如何使用SpringSession与Springsecurity完成网站登录改造
如何使用Spring Session 与 Spring security 完成网站登录改造,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
10年的巴彦网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。全网整合营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整巴彦建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联建站从事“巴彦网站设计”,“巴彦网站推广”以来,每个客户项目都认真落实执行。
上次小黑在文章中介绍了四种分布式一致性 Session 的实现方式,在这四种中最常用的就是后端集中存储方案,这样即使 web 应用重启或者扩容,Session 都没有丢失的风险。
今天我们就使用这种方式对 Session 存储方式进行改造,将其统一存储到 redis 中。
实现方案
我们先来想一下,如果我们不依靠任何框架,自己如何实现后端 Session集中存储。
这里我们假设我们的网站除了某些页面,比如首页可以直接访问以外,其他任何页面都需要登录之后才能访问。
如果需要实现这个需求,这就需要我们对每个请求都进行鉴权,鉴权目的是为了判断用户是否登录,判断用户角色。
如果用户没有登录,我们需要将请求强制跳转到登录页面进行登录。
用户登录之后,我们需要将登录获取到的用户信息存储到 Session中,这样后面请求鉴权只需要判断 Session中是否存在即可。
知道整个流程之后,其实实现原理就不是很难了。
我们可以使用类似 AOP的原理,在每个请求进来之后,都先判断 Session 中是否存在用户信息,如果不存在就跳转到登录页。
整个流程如下所示:
我们可以利用 Servelt Filter实现上述流程,不过上述整套流程,Spring 已经帮我们实现了,那我们就不用重复造轮子了。
我们可以使用 Spring-Session与 Spring-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 过期时间,默认单位为 s server.servlet.session.timeout=600 ## Session 存储到 Redis 键的前缀 spring.session.redis.namespace=test:spring:session ## Redis 相关配置 spring.redis.host=127.0.0.1 spring.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
默认情况下,Session 默认使用HttpSession 序列化方式,这种值看起来不够直观。我们可以将其修改成 json 序列化方式,存储到 redis 中。
@Configuration public class HttpSessionConfig implements BeanClassLoaderAware { private ClassLoader loader; @Bean public RedisSerializer
修改之后 Redis 键值如下所示:
ps:这里 Redis 键值含义,下次分析源码的时候,再做分析。
Spring Session 还存在一个 @EnableRedisHttpSession,我们可以在这个注解上配置 Spring Session 相关配置。
@EnableRedisHttpSession(redisNamespace = "test:session")
需要注意的是,如果使用这个注解,将会导致 application.properties
Session 相关配置失效,也就是说 Spring Session 将会直接使用注解上的配置。
这里小黑比较推荐大家使用配置文件的方式。
好了,Spring Session 到这里我们就接入完成了。
Spring security
上面我们集成了 Spring Session,完成 Session 统一 Redis 存储。接下来主要需要实现请求的登陆鉴权。
这一步我们使用 Spring security 实现统一的登陆鉴权服务,同样的框架的还有 Shiro,这里我们就使用 Spring 全家桶。
首先我们需要依赖的相应的依赖:
org.springframework.boot spring-boot-starter-security
引入上面的依赖之后,应用启动之后将会生成一个随机密码,然后所有的请求将会跳转到一个 Spring security 的页面。
这里我们需要实现自己业务的登陆页,所以我们需要自定义登录校验逻辑。
在 Spring security 我们只需要实现 UserDetailsService
接口,重写 loadUserByUsername
方法逻辑。
@Service public 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
中。
@Configuration public 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 页面。
Login
这里需要注意一点,这里 form表单的请求地址使用 /auth/login
,我们需要在下面配置中修改,默认情况下登录请求的地址需要为 /login
。
接着我们在上面的 SecurityConfig
类增加相应配置方法:
/** * 自定义处理登录处理 * * @param http * @throws Exception */ @Override protected 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 信息实现免登录的功能。
最后我们需要配置一些页面的跳转地址:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 首页 registry.addViewController("/").setViewName("home"); // 登录之后跳转到 home 页 registry.addViewController("/login").setViewName("login"); } }
到此为止,我们已经集成 Spring-Session与 Spring-security完成完整的网站的登录鉴权功能。从这个例子可以看到,引入这个两个框架之后,我们只需要按照 Spring 规范开发即可,其他复杂实现原理我们都不需要自己实现了,这样真的很方便。
看完上述内容,你们掌握如何使用Spring Session 与 Spring security 完成网站登录改造的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
名称栏目:如何使用SpringSession与Springsecurity完成网站登录改造
URL分享:http://cdiso.cn/article/jgspip.html