博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security 之集群Session配置
阅读量:7287 次
发布时间:2019-06-30

本文共 10884 字,大约阅读时间需要 36 分钟。

 

1.   新建Maven项目 cluster-session

 

2.   pom.xml

4.0.0
com.java
cluster-session
1.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.5.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.session
spring-session-data-redis
org.springframework.cloud
spring-cloud-starter-oauth2
2.0.0.RELEASE
org.springframework.session
spring-session
1.3.5.RELEASE
org.springframework
springloaded
1.2.8.RELEASE
provided
org.springframework.boot
spring-boot-devtools
provided
${project.artifactId}
org.apache.maven.plugins
maven-compiler-plugin
1.8
1.8
UTF-8
org.springframework.boot
spring-boot-maven-plugin
repackage

 

3.   ClusterSessionStarter.java

package com.java;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 
 *  * 主启动类 *  * 
* * @author Logan * */@SpringBootApplicationpublic 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 {    @Override    public 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必须配置,否则登录时报空指针异常     */    @Bean    public 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 * */@Configurationpublic class LoginConfig extends WebSecurityConfigurerAdapter {    @Override    protected 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 * */@Componentpublic class SecurityUserDetailsService implements UserDetailsService {    @Autowired    private PasswordEncoder passwordEncoder;    @Override    public 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=8080server.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

            登录        

用户自定义登录页面

登录框
用户名:
密码:

 

12.   main.html

            首页        

Designed by Logan.

 

 

 

 

 

 

 

.

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

你可能感兴趣的文章
Python 函数式编程--装饰器
查看>>
11月28号
查看>>
DAS、NAS、SAN、iSCSI 存储方案概述
查看>>
为VMware esxi主机配置系统日志记录
查看>>
给批量用户设磁盘配额
查看>>
Docker常见问题总结(持续更新)
查看>>
5-6单元练习
查看>>
以普通用户启动的Vim如何保存需要root权限的文件
查看>>
客户端和浏览器都不能连接SVN服务器
查看>>
计划任务
查看>>
华为交换机的命令行
查看>>
限制你的指令只能通过特定的方式来调用
查看>>
男神的补习
查看>>
while数字死循环
查看>>
备份架构——三种基本备份拓扑
查看>>
关于visual assist x插件不能用的解决方案
查看>>
Linux iptables:规则组成
查看>>
HDU 4442 Physical Examination【水题】【思维题】
查看>>
NET 命令 常用方法!
查看>>
我的友情链接
查看>>