1.   新建Maven项目 cluster-session

2.   pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.java</groupId><artifactId>cluster-session</artifactId><version>1.0.0</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version></parent><dependencies><!-- Spring Boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><version>2.0.0.RELEASE</version></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session</artifactId><version>1.3.5.RELEASE</version></dependency><!-- 热部署 --><dependency><groupId>org.springframework</groupId><artifactId>springloaded</artifactId><version>1.2.8.RELEASE</version><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>provided</scope></dependency></dependencies><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>

3.   ClusterSessionStarter.java

package com.java;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** <blockquote><pre>* * 主启动类* * </pre></blockquote>* * @author Logan**/
@SpringBootApplication
public class ClusterSessionStarter {public static void main(String[] args) {SpringApplication.run(ClusterSessionStarter.class, args);}}

4.   SessionInformationExpiredStrategyImpl.java

package com.java.session;import java.io.IOException;import javax.servlet.ServletException;
import javax.utils.ResponseUtils;import org.springframework.security.web.session.SessionInformationExpiredEvent;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;/*** Session过期处理策略* * @author Logan* @createDate 2019-02-14* @version 1.0.0**/
public class SessionInformationExpiredStrategyImpl implements SessionInformationExpiredStrategy {@Overridepublic void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {ResponseUtils.write(event.getResponse(), "你的账号在另一地点被登录");}}

5.   ApplicationContextConfig.java

package com.java.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;/*** 配置文件类* * @author Logan* @createDate 2019-02-14* @version 1.0.0**/
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class ApplicationContextConfig {/*** 配置密码编码器,Spring Security 5.X必须配置,否则登录时报空指针异常*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

6.   LoginConfig.java

package com.java.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import com.java.session.SessionInformationExpiredStrategyImpl;/*** 登录相关配置* * @author Logan* @createDate 2019-02-14* @version 1.0.0**/
@Configuration
public class LoginConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()// 设置不需要授权的请求.antMatchers("/js/*", "/login.html").permitAll()// 其它任何请求都需要验证权限
                .anyRequest().authenticated()// 设置自定义表单登录页面.and().formLogin().loginPage("/login.html")// 设置登录验证请求地址为自定义登录页配置action ("/login/form").loginProcessingUrl("/login/form")// 设置默认登录成功跳转页面.defaultSuccessUrl("/main.html")/* session 管理 */.and().sessionManagement()// 设置Session失效跳转页面.invalidSessionUrl("/login.html")// 设置最大Session数为1.maximumSessions(1)// 设置Session过期处理策略.expiredSessionStrategy(new SessionInformationExpiredStrategyImpl()).and()// 暂时停用csrf,否则会影响验证
                .and().csrf().disable();}}

7.   SecurityUserDetailsService.java

package com.java.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;/*** UserDetailsService实现类* * @author Logan* @createDate 2019-02-14* @version 1.0.0**/
@Component
public class SecurityUserDetailsService implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 数据库存储密码为加密后的密文(明文为123456)String password = passwordEncoder.encode("123456");System.out.println("username: " + username);System.out.println("password: " + password);// 模拟查询数据库,获取属于Admin和Normal角色的用户User user = new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("Admin,Normal"));return user;}}

8.   ResponseUtils.java

package javax.utils;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;import javax.servlet.http.HttpServletResponse;import com.fasterxml.jackson.databind.ObjectMapper;/*** HTTP 输出响应内容工具类* * @author Logan* @createDate 2019-02-14* @version 1.0.0**/
public class ResponseUtils {/*** 发送HTTP响应信息* * @param response HTTP响应对象* @param message 信息内容* @throws IOException 抛出异常,由调用者捕获处理*/public static void write(HttpServletResponse response, String message) throws IOException {response.setContentType("text/html;charset=UTF-8");try (PrintWriter writer = response.getWriter();) {writer.write(message);writer.flush();}}/*** 发送HTTP响应信息,JSON格式* * @param response HTTP响应对象* @param message 输出对象* @throws IOException 抛出异常,由调用者捕获处理*/public static void write(HttpServletResponse response, Object message) throws IOException {response.setContentType("application/json;charset=UTF-8");ObjectMapper mapper = new ObjectMapper();try (PrintWriter writer = response.getWriter();) {writer.write(mapper.writeValueAsString(message));writer.flush();}}/*** 下载文件* * @param response HTTP响应对象* @param message 输出对象* @throws IOException 抛出异常,由调用者捕获处理*/public static void write(HttpServletResponse response, File file) throws IOException {String fileName = file.getName();try (OutputStream out = response.getOutputStream();FileInputStream in = new FileInputStream(file);) {// 对文件名进行URL转义,防止中文乱码fileName = URLEncoder.encode(fileName, "UTF-8");// 空格用URLEncoder.encode转义后会变成"+",所以要替换成"%20",浏览器会解码回空格fileName = fileName.replace("+", "%20");// "+"用URLEncoder.encode转义后会变成"%2B",所以要替换成"+",浏览器不对"+"进行解码fileName = fileName.replace("%2B", "+");response.setContentType("application/x-msdownload;charset=UTF-8");response.setHeader("Content-Disposition", "attachment; filename=" + fileName);byte[] bytes = new byte[4096];int len = -1;while ((len = in.read(bytes)) != -1) {out.write(bytes, 0, len);}out.flush();}}}

9.   application.properties

server.port=8080
server.servlet.session.timeout=600spring.session.store-type=redis# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0# Redis服务器地址
spring.redis.host=192.168.32.10# Redis服务器连接端口
spring.redis.port=6379# Redis服务器连接密码(默认为空)
spring.redis.password=redis123.# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=10# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=5# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0# 连接超时时间(毫秒)
spring.redis.timeout=10000spring.cache.redis.time-to-live=600

10.    src/main/resources 下静态资源文件如下:

static/login.html

static/main.html

11.   login.html

<!DOCTYPE html>
<html><head><title>登录</title><meta http-equiv="content-type" content="text/html; charset=UTF-8" /></head><body><!--登录框--><div align="center"><h2>用户自定义登录页面</h2><fieldset style="width: 300px;"><legend>登录框</legend><form action="/login/form" method="post"><table><tr><th>用户名:</th><td><input name="username" value="Logan" /> </td></tr><tr><th>密码:</th><td><input type="password" name="password" value="123456" /> </td></tr><tr><th></th><td></td></tr><tr><td colspan="2" align="center"><button type="submit">登录</button></td></tr></table></form></fieldset></div></body></html>

12.   main.html

<html><head><title>首页</title><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><script>window.onclick = function() {window.open("http://www.cnblogs.com/jonban/");}</script></head><body style="background-color: cyan;text-align: center;"><h1><span style="text-align:center;color:purple;cursor: pointer;">Designed by Logan.</span></h1><canvas id="c"></canvas><script>var b = document.body;var c = document.getElementsByTagName('canvas')[0];var a = c.getContext('2d');document.body.clientWidth;</script><script>with(m = Math)C = cos, S = sin, P = pow, R = random;c.width = c.height = f = 613;h = -250;function p(a, b, c) {if(c > 60)return [S(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) - S(b) * 50,b * f + 50,625 + C(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) + b * 400,a * 1 - b / 2, a];A = a * 2 - 1;B = b * 2 - 1;if(A * A + B * B < 1) {if(c > 37) {n = (j = c & 1) ? 6 : 4;o = .5 / (a + .01) + C(b * 125) * 3 - a * 300;w = b * h;return [o * C(n) + w * S(n) + j * 610 - 390, o * S(n) - w * C(n) + 550 - j * 350, 1180 + C(B + A) * 99 - j * 300, .4 - a * .1 + P(1 - B * B, -h * 6) * .15 - a * b * .4 + C(a + b) / 5 + P(C((o * (a + 1) + (B > 0 ? w : -w)) / 25), 30) * .1 * (1 - B * B), o / 1e3 + .7 - o * w * 3e-6]}if(c > 32) {c = c * 1.16 - .15;o = a * 45 - 20;w = b * b * h;z = o * S(c) + w * C(c) + 620;return [o * C(c) - w * S(c), 28 + C(B * .5) * 99 - b * b * b * 60 - z / 2 - h, z, (b * b * .3 + P((1 - (A * A)), 7) * .15 + .3) * b, b * .7]}o = A * (2 - b) * (80 - c * 2);w = 99 - C(A) * 120 - C(b) * (-h - c * 4.9) + C(P(1 - b, 7)) * 50 + c * 2;z = o * S(c) + w * C(c) + 700;return [o * C(c) - w * S(c), B * 99 - C(P(b, 7)) * 50 - c / 3 - z / 1.35 + 450, z, (1 - b / 1.2) * .9 + a * .1, P((1 - b), 20) / 4 + .05]}}setInterval('for(i=0;i<1e4;i++)if(s=p(R(),R(),i%46/.74)){z=s[2];x=~~(s[0]*f/z-h);y=~~(s[1]*f/z-h);if(!m[q=y*f+x]|m[q]>z)m[q]=z,a.fillStyle="rgb("+~(s[3]*h)+","+~(s[4]*h)+","+~(s[3]*s[3]*-80)+")",a.fillRect(x,y,1,1)}', 0)</script></body></html>

.

转载于:https://www.cnblogs.com/jonban/p/cluster-session.html

Spring Security 之集群Session配置相关推荐

  1. spring 使用redis集群配置

    上面两篇介绍了redis集群的配置合一些基本的概念,所以接下来当然是要在项目中使用咯,redis的java支持已经做的非常好了,所以我们来试着使用这些api来进行redis的操作,首先我们需要操作re ...

  2. Nginx+memcached+tomcat配置集群session共享负载均衡

    Nginx+memcached+tomcat配置集群session共享负载均衡 配置环境: windows xp下 jdk1.7.0_10      nginx-1.2.6  (附下载)      m ...

  3. redis安装、持久化、数据类型、常用操作、操作键值、安全设置、慢查询日志、存储session、主从配置、集群介绍、集群搭建配置、集群操作,php安装redis扩展...

    21.9 redis介绍 21.10 redis安装 21.11 redis持久化 21.12 redis数据类型 21.13/21.14/21.15 redis常用操作 21.16 redis操作键 ...

  4. 一步步教你Hadoop多节点集群安装配置

    一步步教你Hadoop多节点集群安装配置 1.集群部署介绍 1.1 Hadoop简介  Hadoop是Apache软件基金会旗下的一个开源分布式计算平台.以Hadoop分布式文件系统HDFS(Hado ...

  5. Oracle Dataguard(主库为 Oracle rac 集群)配置教程(01)—— dataguard 服务器安装 Oracle 软件

    Oracle Dataguard(主库为 Oracle rac 集群)配置教程(01)-- dataguard 服务器安装 Oracle 软件 / 本专栏详细讲解 Oracle Dataguard(O ...

  6. Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:爱宝贝丶 my.oschina.net/zhangxufen ...

  7. Elasticsearch7.x 安装及集群的配置

    简介 首先引用 Elasticsearch (下文简称 ES)官网的一段描述: Elasticsearch 是一个分布式.RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例. 作为 ...

  8. redis -Spring与Jedis集群 Sentinel

    2019独角兽企业重金招聘Python工程师标准>>> redis -Spring与Jedis集群 Sentinel 博客分类: 缓存 首先不得不服Spring这个宇宙无敌的开源框架 ...

  9. Jetty9.2.2集群Session共享

    为什么80%的码农都做不了架构师?>>>    针对Jetty就不过多的介绍了,自行研究去吧! 1.准备环境 MySQL数据库:下载地址:自行百度. jetty-distributi ...

最新文章

  1. Java开发必须掌握的线上问题排查命令
  2. Java竞赛目的_ACM竞赛 Java编程小结
  3. SVN中 “containing working copy admin area is missin
  4. html iframe 播放视频播放,播放iframe视频点击链接javascript
  5. 张俊红21岁的年度总结
  6. 非插件实现回复可见效果
  7. Spring表达式语言使用
  8. mysql allowed packet_修改mysql的max_allowed_packet值
  9. 24小时学通LINUX内核系列
  10. 手动写一个上传图片的组件,不适用插件,包括限制图片大小,格式
  11. Selenium下载页面上的图片
  12. 00-高通msm8953 Android驱动教程
  13. 论文解读:记忆网络(Memory Network)
  14. 统计学+变异+变异系数
  15. word突然不能保存只能另存为
  16. 过滤百度广告+搜索热点+adblock规则快速入门
  17. 我的2017,五味杂陈
  18. java基础多线程抢红包_java多线程模拟抢红包功能
  19. Epson机械手简单实例编程
  20. 金融危机,教你从网络上找到一份好兼职

热门文章

  1. redis在PHP中的基本使用案例
  2. python基础===Number
  3. 网友脑洞大开 用 Emoji 开发“俏皮”编程语言
  4. 找回 macOS Sierra 中的“任何来源”选项
  5. nginx的优先匹配规则
  6. 实验 4 在分支循环结构中调用自定义函数
  7. 测试sql语句执行时间
  8. 同济大学计算机云南2019,同济大学录取分数线2019(在各省市录取数据)
  9. android定义空字符串数组,android – retrofit:处理可以是空字符串或数组的属性
  10. 空间统计分析_5.5 空间数据库的发展趋势