本文讲述spring-boot工程中使用spring-session机制进行安全认证,并且通过redis存储session,满足集群部署、分布式系统的session共享。

java工程中,说到权限管理和安全认证,我们首先想到的是Spring Security和Apache Shiro,这两者均能实现用户身份认证和复杂的权限管理功能。但是如果我们只是想实现身份认证(如是否登录、会话是否超时),使用session管理即可满足。本文目录如下:

目录:

  1. 创建spring-boot项目

  2. 用户管理

  3. 用户身份认证

  4. spring-session配置

  5. 使用redis共享session


一、创建spring-boot项目

1、工程使用idea+gradle搭建,jdk1.8,spring-boot版本2.0.2.RELEASE,数据库postgreSQL,持久层spring-data-jpa;
2、新建spring-boot项目,工程type选择Gradle Project;
3、勾选初始化依赖如下:

初始化依赖

创建完成后gradle.build文件内容如下:

buildscript {
ext {
springBootVersion = '2.0.2.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
} apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management' group = 'louie.share'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8 repositories {
mavenCentral()
} dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-web')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('org.postgresql:postgresql')
testCompile('org.springframework.boot:spring-boot-starter-test')
}

4、application.yml配置数据库及jpa

spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:5432/louie
data-username: louie
password: louie1234
jpa:
database: postgresql
hibernate:
ddl-auto: update

二、用户管理

1、创建User实体类

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable; /**
* 用户实体
* @author louie
* @date created in 2018-5-12 17:28
*/
@Entity
@Table(name = "b_id_user")
public class User implements Serializable{
@Id
@GenericGenerator(name = "idGenerator",strategy = "uuid")
@GeneratedValue(generator = "idGenerator")
private String id; @NotBlank(message = "account can not be empty")
private String account;
@NotBlank(message = "password can not be empty")
private String password;
@NotBlank(message = "name can not be empty")
private String name; //省略getter、setter
}

2、用户服务接口

import louie.share.sessionredis.bean.User;

/**
* 用户服务接口
* @author louie
* @date created in 2018-5-12 17:40
*/
public interface UserService {
/**
* save user
* @param user
* @return 保存后的用户信息
*/
User saveUser(User user); /**
* find user by account
* @param account
* @return
*/
User findByAccount(String account); /**
* user login
* @param account
* @param password
* @return
*/
BaseResponse login(String account,String password);
}

这里省略接口的实现,您可以访问我的github和码云查看该工程的源代码(代码地址见文档底部)。

3、用户管理控制器

import louie.share.sessionredis.bean.BaseResponse;
import louie.share.sessionredis.bean.User;
import louie.share.sessionredis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; /**
* 用户管理相关控制器
* @author louie
* @date created in 2018-5-12 17:26
*/ @RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService; /**
* save user
* @param user
* @return
*/
@RequestMapping(value = "/save",method = RequestMethod.POST)
public User save(User user){
return userService.saveUser(user);
} /**
* find user by account
* @param account
* @return
*/
@RequestMapping(value = "/find/{account}",method = RequestMethod.GET)
public User find(@PathVariable String account){
return userService.findByAccount(account);
} /**
* user login
* @param account
* @param password
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public BaseResponse login(String account,String password){
return userService.login(account,password);
}
}

4、创建用户
运行Application类启动服务,使用postMan访问http://localhost:8080/user/save服务创建用户:

创建用户

三、用户身份认证

1、使用postMan访问http://localhost:8080/user/login进行用户登录校验:

微信截图_20180512184322.png-66.2kB

四、spring-session配置

该部分为重点内容了,目的是实现访问资源时的安全认证、超时控制和用户登出功能。
1、修改用户登录login控制,登录成功后将用户信息写入session

/**
* user login
* @param account
* @param password
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public BaseResponse login(String account, String password,HttpSession session){
BaseResponse response = userService.login(account,password);
if (response.isOk()){
session.setAttribute(session.getId(),response.getData());
}
return response;
}

2、新增用户登出logout功能,将用户信息移除session

    /**
* user logout
* @param session
* @return
*/
@RequestMapping(value = "/logout")
public String logout(HttpSession session){
session.removeAttribute(session.getId());
return "user logout success";
}

3、设置session过期时间

spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:5432/louie
data-username: louie
password: louie1234
jpa:
database: postgresql
hibernate:
ddl-auto: update
server:
servlet:
session:
timeout: "PT10M"

以下是为session有效时长为10分钟:

设置session过期时间

4、添加拦截器,通过session判断用户是否有效

import com.alibaba.fastjson.JSON;
import louie.share.sessionredis.bean.BaseResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; /**
* @author louie
* @date created in 2018-5-12 19:02
*/
@Configuration
public class SessionCofig implements WebMvcConfigurer{ @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SecurityInterceptor())
//排除拦截
.excludePathPatterns("/user/login")
.excludePathPatterns("/user/logout") //拦截路径
.addPathPatterns("/**");
} @Configuration
public class SecurityInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
HttpSession session = request.getSession();
if (session.getAttribute(session.getId()) != null){
return true;
}
response.getWriter().write(JSON.toJSONString(
new BaseResponse(){{
setOk(false);
setMessage("please login first");
}}
));
return false;
}
}
}

5、使用postMan访问http://localhost:8080/user/find/101,用户未登录,被拦截:

用户未登录拦截

访问http://localhost:8080/user/login登录:

用户登录

再次访问访问http://localhost:8080/user/find/101

登录后访问

五、使用redis存储session

1、添加依赖

compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.session:spring-session-data-redis')

2、application.yml中添加配置

redis配置

源代码:

spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:5432/louie
data-username: louie
password: louie1234
jpa:
database: postgresql
hibernate:
ddl-auto: update
redis:
database: 0
host: localhost
port: 6379
password: xonro_vflow
session:
store-type: redis
server:
servlet:
session:
timeout: "PT10M"

3、启动redis和application类,用户登录,查看redis内容:

debug查看:

debug查看session信息

redis内容:

redis内容

工程代码已共享至github和码云,欢迎探讨学习。


-END-

Spring Boot+redis存储session,满足集群部署、分布式系统的session共享的更多相关文章

  1. Redis 中常见的集群部署方案

    Redis 的高可用集群 前言 几种常用的集群方案 主从集群模式 全量同步 增量同步 哨兵机制 什么是哨兵机制 如何保证选主的准确性 如何选主 选举主节点的规则 哨兵进行主节点切换 切片集群 Redi ...

  2. 使用Tomcat+Redis来实现集群部署中的Session共享问题

    一.工作中因为要使用到Tomcat集群部署,此时就涉及到了Session共享问题,主要有三种解决方案: 1.使用数据库来存储Session 2.使用Cookie来存储Session 3.使用Redis ...

  3. 使用Tomcat-redis-session-manager来实现Tomcat集群部署中的Session共享

    一.工作中因为要使用到Tomcat集群部署,此时就涉及到了Session共享问题,主要有三种解决方案: 1.使用数据库来存储Session 2.使用Cookie来存储Session 3.使用Redis ...

  4. spring集成Redis(单机、集群)

    一.单机redis配置 1. 配置redis连接池 <bean id="jedisPoolConfig" class="redis.clients.jedis.Je ...

  5. redis 配置文件解释 以及集群部署

    redis是一款开源的.高性能的键-值存储(key-value store),和memcached类似,redis常被称作是一款key-value内存存储系统或者内存数据库,同时由于它支持丰富的数据结 ...

  6. redis 3.0的集群部署

    转载请注明出处:http://hot66hot.iteye.com/admin/blogs/2050676 最近研究redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到re ...

  7. (转)redis 3.0的集群部署

    一:关于redis cluster 1:redis cluster的现状 reids-cluster计划在redis3.0中推出,可以看作者antirez的声明:http://antirez.com/ ...

  8. Redis 3.0.0 集群部署

    简述: 1.0.1:redis cluster的现状 目前redis支持的cluster特性 1):节点自动发现 2):slave->master 选举,集群容错 3):Hot reshardi ...

  9. NAT集群部署solo之session server

    author:JevonWei 版权声明:原创作品 使用Nginx做代理服务器,部署solo,使用session server做会话黏滞 拓扑图 环境 tomcatA 172.16.253.108 t ...

随机推荐

  1. Java 7 使用TWR(Try-with-resources)完成文件copy

    try-with-resources语句是声明了一个或多个资源的try语句块.在java中资源作为一个对象,在程序完成后必须关闭.try-with-resources语句确保每个资源在语句结束时关闭. ...

  2. Heartbleed心脏出血漏洞原理分析

    Heartbleed心脏出血漏洞原理分析 2017年01月14日 18:14:25 阅读数:2718 1. 概述    OpenSSL在实现TLS和DTLS的心跳处理逻辑时,存在编码缺陷.OpenSS ...

  3. spring boot项目升级到2.0.1,提示java.lang.ClassNotFoundException: org.apache.log4j.Logger错误

    首先肯定是版本出现了一点兼容问题 所以我就进入项目,查看依赖树,cd到项目目录下,mvn dependency:tree 我看到我的项目原先是1.5.9和现在2.0.1的区别在于org.slf4j的依 ...

  4. java 小心使用float和double他可能不如你所想

    public static void main(String[] args) { double funds=1.00; ; // ; ;funds>=price;price+=.){ funds ...

  5. 【mysql】decimal数据类型

    1.float.double.decimal float:浮点型,4字节,32bit. double:双精度实型,8字节,64位 decimal:数字型,128bit,不存在精度损失,常用于银行帐目计 ...

  6. # 2019-2020.3 《java程序设计》第一周学习总结

    2019-2020-3 <Java 程序设计>第一周学习总结 在本周的学习中,学习到了好多也收获了好多,从最基础的安装虚拟机开始,根据老师的博客中的教程一步一步的进行,在这过程中也遇到了好 ...

  7. 系统性能--CPU

    对于cpu,目前比较关心的是cpu的利用率还有cpu的load,或者还有cpu运行队列. cpu利用率 cpu利用率分为sys,us.分别为操作系统和用户进程所占用的cpu利用率.sys的占用,一般是 ...

  8. bootstrap的化妆页面

    Glyphicons 字体图标 所有可用的图标 包括260个来自 Glyphicon Halflings 的字体图标.Glyphi cons Halflings 一般是收费的,但是他们的作者允许 Bo ...

  9. 请教:WCF速度似乎比Remoting慢

    两段极为相似的代码,主要想看看过输与序列化过程两者的用时差异,结果10000次的调用,WCF用了11秒多,remoting用了5秒不到!这是测试的源代码 Remoting的服务端 public cla ...

  10. 【接口时序】3、UART串口收发的原理与Verilog实现

    一.软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE14.7 3.仿真工具:ModelSim-10.4-SE 硬件平台: 1.FPGA型号:XC6SLX45- ...