SpringBoot整合SpringSecurit,实现ajax的登录、退出、权限校验

1、本文章中SpringBoot整合SpringSecurity,只是基于session方式,并且没有使用到redis。

2、登录、登出都是通过ajax的方式进行。

项目目录:

1、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.example.springboot.security.demo</groupId>
	<artifactId>springboot-security-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot-security-demo</name>
	<description>springboot-security project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<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</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<!-- thymeleaf 模板引擎-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<!-- spring security依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.0</version>
		</dependency>

		<!--谷歌处理json的工具包-->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.0</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
2、SecurityConfig 配置类
package com.example.springboot.security.demo.config.security;

import com.example.springboot.security.demo.handle.UserAuthenticationAccessDeniedHandler;
import com.example.springboot.security.demo.handle.UserLoginAuthenticationFailureHandler;
import com.example.springboot.security.demo.handle.UserLoginAuthenticationSuccessHandler;
import com.example.springboot.security.demo.handle.UserLogoutSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.annotation.Resource;

/**
 * 配置 Security
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//开启security的权限校验注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 用户验证成功处理类
     */
    @Resource
    private UserLoginAuthenticationSuccessHandler userLoginAuthenticationSuccessHandler;

    /**
     * 用户验证失败处理类
     */
    @Resource
    private UserLoginAuthenticationFailureHandler userLoginAuthenticationFailureHandler;

    /**
     * 无权限操作时的处理类
     */
    @Resource
    private UserAuthenticationAccessDeniedHandler userAuthenticationAccessDeniedHandler;

    /**
     * 用户登出处理类
     */
    @Resource
    private UserLogoutSuccessHandler userLogoutSuccessHandler;



    //配置安全拦截机制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();//禁用CSRF控制,即spring security不再限制CSRF,即跨越访问

        http
                .authorizeRequests()
                .antMatchers("/static/**").permitAll()//不需要登录认证就可以访问,静态资源等不需要验证
                .antMatchers("/public/**").anonymous()//以public开头的接口,都可以匿名访问,即不用登录就可以访问
                .anyRequest().authenticated();//其他路径必须验证身份
        http
                .formLogin()
                .loginPage("/login-view.html")//登录页面,加载登录的html页面
                .loginProcessingUrl("/login")//发送Ajax请求的路径
                .usernameParameter("username")//请求验证参数
                .passwordParameter("password")//请求验证参数
                .successHandler(userLoginAuthenticationSuccessHandler)//验证成功处理
                .failureHandler(userLoginAuthenticationFailureHandler)//验证失败处理
                .permitAll();//登录页面无需设置验证

        http
                .logout()
                .logoutUrl("/logout")//登出路径
                .logoutSuccessHandler(userLogoutSuccessHandler)//登出处理
                .permitAll()//不需要身份认证
                .and()
                .exceptionHandling().accessDeniedHandler(userAuthenticationAccessDeniedHandler);//无权限时的处理
    }

    /**
     * 配置身份验证管理器
     * @param auth
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider());
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        //spring security 的登录实现
        daoAuthenticationProvider.setUserDetailsService(new UserDetailsServiceImpl());
        //使用BCrypt进行密码加密校验
        daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        //设置hideUserNotFoundExceptions为false
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        return daoAuthenticationProvider;
    }
}
3、UserDetailsServiceImpl:spring security 的登录实现
package com.example.springboot.security.demo.config.security;

import com.example.springboot.security.demo.model.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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * spring security 的登录实现
 */
@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    //这里通过注入,查询数据库实现登录
    /*@Resource
    private UserService userService;*/

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //登录账号
        System.out.println("username="+username);
        //1、这里是从数据库查询出来的对象
        User user = new User();
        user.setUsername(username);
        //这个加密密码是456
        user.setPassword("$2a$10$zgnAvX32nq.NaWtQ0SrMGOiJUH4jtTCXtLHWPPWBnHP4knzndbROm");

        //保存用户账号到session中,这样在controller中就可以直接获取
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        request.setAttribute("username",username);

        //模拟用户查询出来有问题
        if (username.equals("zhangsan")){
           throw new UsernameNotFoundException("用户不存在");
        }
        if (username.equals("zhangsan2")){
            throw new UsernameNotFoundException("用户被禁用");
        }

        //从数据库中查询用户的权限信息
        List<String> permissions = new ArrayList<>();
        permissions.add("sysUserInfo:view");
        permissions.add("sysUserInfo:update");
        permissions.add("sysUserInfo:delete");
        user.setPermissionList(permissions);

        //如果不重写UserDetails,那么可以用下面的这种写法
//        String[] permissionArray = new String[permissions.size()];
//        permissions.toArray(permissionArray);
//        UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(username).password("123").authorities(permissionArray).build();

        return user;
    }
}
4、无权限操作时的处理类
package com.example.springboot.security.demo.handle;

import com.example.springboot.security.demo.common.JsonData;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 无权限操作时的处理类
 */
@Slf4j
@Component("UserAuthenticationAccessDeniedHandler")
public class UserAuthenticationAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                       AccessDeniedException e) throws IOException, ServletException {
        log.info("{}","无权限处理");
        JsonData jsonData = new JsonData(500,"error");
        String json = new Gson().toJson(jsonData);
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();

        out.write(json);
        out.flush();
        out.close();
    }
}
5、用户验证失败处理类
package com.example.springboot.security.demo.handle;

import com.example.springboot.security.demo.common.JsonData;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 用户验证失败处理类
 */
@Slf4j
@Component("UserLoginAuthenticationFailureHandler")
public class UserLoginAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {



    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {

        String username = (String) request.getAttribute("username");
        System.out.println("登录用户:"+username);

        JsonData jsonData = null;

        /**
         * UserDetailsService 校验用户时,主动抛出的错误,如:用户信息不存在 用户被禁用等
         */
        if (exception instanceof UsernameNotFoundException){
            jsonData = new JsonData(402,exception.getMessage());
        }

        /**
         * 密码错误
         */
        if (exception instanceof BadCredentialsException){
            log.info(exception.getMessage());
            jsonData = new JsonData(403,"账号或密码错误");

            // String user_name = userService.findByUserNameAttemps(username);
            // if (user_name == null){
            //     String time = DateUtil.getTimeToString();
            //     UserLoginAttempts userLoginAttempts = new UserLoginAttempts(username,1,time);
            //     userService.saveAttempts(userLoginAttempts);
            // }


            // if(userService.getAttempts(username) == 1){
            //     String time = DateUtil.getTimeToString();
            //     userService.setAttempts(username,time);
            //     jsonData = new JsonData(403,"密码错误,你还有2次机会进行登录操作");
            // }
            // else if(userService.getAttempts(username) == 3){
            //     User user = userService.findByUserName(username);
            //     userService.LockUser(user.getId());
            //     jsonData = new JsonData(403,"最后一次尝试登陆失败,你已经被冻结了");
            // }
            // else if (userService.getAttempts(username) ==2 ){
            //     String time = DateUtil.getTimeToString();
            //     userService.setAttempts(username,time);
            //     jsonData = new JsonData(403,"密码错误,你还有1次机会进行登录操作");
            // }
        }

        String json = new Gson().toJson(jsonData);
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();

        out.write(json);
        out.flush();
        out.close();
    }
}
6、用户验证成功处理类
package com.example.springboot.security.demo.handle;

import com.example.springboot.security.demo.common.JsonData;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 用户验证成功处理类
 */
@Slf4j
@Component("UserLoginAuthenticationSuccessHandler")
public class UserLoginAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        JsonData jsonData = new JsonData(200,"认证OK");
        String json = new Gson().toJson(jsonData);
        log.info("{}","handle_success");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();

        out.write(json);
        out.flush();
        out.close();
    }
}
7、用户登出处理类
package com.example.springboot.security.demo.handle;

import com.example.springboot.security.demo.common.JsonData;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 用户登出处理类
 */
@Slf4j
@Component("UserLogoutSuccessHandler")
public class UserLogoutSuccessHandler implements LogoutSuccessHandler{

    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        JsonData jsonData = new JsonData(200,"退出成功");
        String json = new Gson().toJson(jsonData);
        log.info("{}","LogOut*******Success");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();

        out.write(json);
        out.flush();
        out.close();
    }
}

主要的是这几个配置,其他的配置可以通过源代码访问:

qw/springboot-security-demo

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

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

相关文章

栈的特性及代码实现(C语言)

目录 栈的定义 栈的结构选取 链式储存结构和顺序栈储存结构的差异 栈的代码实现 "stack.h" "stack.c" 总结 栈的定义 栈&#xff1a;栈是限定仅在表尾进行插入和删除操作的线性表。 我们把运行插入的和删除的一段叫做栈顶&#xff08;TOP&#xff…

JVM学习-彻底搞懂Java自增++

从字节码角度分析i和i的区别 public void method6() {int i 10;i; //在局部变量表上直接加1}public void method7() {int i 10;i; //字节码同i}public void method8() {int i 10;int a i; //通过下图可以看出先将局部变量表中的值push到操作数栈&#xff0c;然…

视频监控平台AS-V1000 的场景管理,一键查看多画面视频的场景配置、调用、管理(一键浏览多路视频)

目录 一、场景管理的定义 二、场景管理的功能和特点 1、功能 &#xff08;1&#xff09;场景配置 &#xff08;2&#xff09;实时监控 &#xff08;3&#xff09;权限管理 2、特点 三、AS-V1000的场景配置和调用 1、场景配置 &#xff08;1&#xff09;实时视频预览 …

数据库查询——kettle开发20

一、数据库查询 数据库查询就是数据库里面的左连接&#xff0c;左连接就是两张表执行左关联查询&#xff0c;把左边的表数据全部查询出来。 如图所示我们在进行数据库查询操作时&#xff0c;我们首先需建立数据库连接&#xff0c;输入表名和查询需要的关键字&#xff0c;最后…

29【PS 作图】宫灯 夜景转换

夜景转化 1 原图 2 选中要变换的图层,然后点击“颜色查找” 再3DLUT文件中,选择moonlight.3DL,可以快速把图层变成偏夜景的颜色 结果如下: 3 选择“曲线” 把曲线 右边往上调【亮的更亮】,左边往下调【暗的更暗】 4 添加灯光 新建一个图层

宝塔下应该用 Memcached 还是 Redis?

明月最近在跟几个使用宝塔面板的客户运维的时候发现不少站长不知道如何选择 Memcached 和 Redis&#xff0c;甚至都说不清楚 Memcached 或者 Redis 具体是用来干啥的&#xff1f;甚至还碰到过一个站长 Memcached 和 Redis 都安装了&#xff0c;但一个都没有用&#xff0c;就那么…

数据中心、HPC、AI等应用场景互联协议混战哪家强?

生成式人工智能快速发展对算力与存力呈指数需求增长&#xff0c;进一步加剧了算力与存力之间既有矛盾&#xff0c;时代在呼唤更大的运力&#xff08;即计算与存储之间的数据传输&#xff09;--AIGC时代需要更大带宽&#xff0c;更为快速的数据传输路径。 众所周知&#xff0c;P…

CTFHUB技能树——SSRF(一)

目录 一、SSRF(服务器端请求伪造) 漏洞产生原理: 漏洞一般存在于 产生SSRF漏洞的函数&#xff08;PHP&#xff09;&#xff1a; 发现SSRF漏洞时&#xff1a; SSRF危害&#xff1a; SSRF漏洞利用手段&#xff1a; SSRF绕过方法&#xff1a; 二、CTFHUB技能树 SSRF 1.Ht…

大数据技术Hbase列数据库——topic1

目录 搭建单机版Hbase验证方法一验证方法二 搭建单机版Hbase 验证方法一 使用 jps 命令查看 HMaster 进程是否启动 首先使用xftp 7上传hbase-2.1.0安装压缩包到虚拟机进行解压缩到某一地址&#xff0c;这里解压缩到了上传的路径即/root/software/ tar -zxvf hbase-2.1.0-bi…

AIGC 009-DaLLE2遇见达利!文生图过程中另外一种思路。

AIGC 009-DaLLE2遇见达利&#xff01;文生图过程中另外一种思路。 0 论文工作 首先&#xff0c;遇见达利是我很喜欢的名字&#xff0c;达利是跟毕加索同等优秀的画家。这个名字就很有意思。 这篇论文提出了一种新颖的分层文本条件图像生成方法&#xff0c;该方法利用 CLIP&…

Llama模型家族之使用 Supervised Fine-Tuning(SFT)微调预训练Llama 3 语言模型(十) 使用 LoRA 微调常见问题答疑

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

[SWPUCTF 2022 新生赛]奇妙的MD5... ...

目录 [SWPUCTF 2022 新生赛]奇妙的MD5 [GDOUCTF 2023]受不了一点 [LitCTF 2023]作业管理系统 注入点一&#xff1a;文件上传 注入点二&#xff1a;创建文件直接写一句话木马 注入点三&#xff1a;获取数据库备份文件 [LitCTF 2023]1zjs [SWPUCTF 2022 新生赛]奇妙的MD5 …

【高校科研前沿】湖北工业大学为第一署名单位在《Science》发表Letters文章:应对青藏高原河流泥沙激增

文章简介 论文名称&#xff1a;Combating sediment surge in Tibetan rivers&#xff08;应对青藏高原河流泥沙激增&#xff09; 相关作者及单位&#xff1a;杨洪教授&#xff08;英国雷丁大学&#xff09;&刘德富教授&#xff08;湖北工业大学&#xff09;&Julian R…

代码随想录算法训练营第十四天(py)| 二叉树 | 递归遍历、迭代遍历、统一迭代

1 理论基础 1.1 二叉树的种类 满二叉树 只有度为0和2的节点&#xff0c;且度为0的节点在同一层。 深度为k&#xff0c;有2^k-1个节点 完全二叉树 除了最底层可能没填满&#xff0c;其余每层节点数都达到最大。并且最底层节点全部集中在左边。 二叉搜索树 是一个有数值…

【JVM精通之路】垃圾回收-三色标记算法

首先预期你已经基本了解垃圾回收的相关知识&#xff0c;包括新生代垃圾回收器&#xff0c;老年代垃圾回收器&#xff0c;以及他们的算法&#xff0c;可达性分析等等。 先想象一个场景 最开始黑色节点是GC-Roots的根节点&#xff0c;这些对象有这样的特点因此被选为垃圾回收的根…

Window VScode配置Conda教程(成功版)

VScode配置Conda 参考博文&#xff1a;https://blog.csdn.net/qq_51831335/article/details/126757014Anaconda安装&#xff08;注意勾选自动配置环境变量&#xff01;&#xff09; 官网&#xff1a;https://www.anaconda.com/download/success VScode配置 python插件安装安装 …

Gin与OpenAPI(Swagger)的使用

一、背景 1、swagger与openapi Swagger&#xff1a; 一种用于描述RESTFUL API的规范&#xff0c;它提供了一种简单的来描述API的请求和相应参数、错误码、返回数据类型等信息&#xff0c;是开发者可以方便了解API使用方式。 官网: https://swagger.io/ OpenAPI : 始于 …

京东二面:Sychronized的锁升级过程是怎样的

引言 Java作为主流的面向对象编程语言&#xff0c;提供了丰富的并发工具来帮助开发者解决多线程环境下的数据一致性问题。其中&#xff0c;内置的关键字"Synchronized"扮演了至关重要的角色&#xff0c;它能够确保在同一时刻只有一个线程访问特定代码块或方法&#…

Redis常用命令——Hash篇

前面我们讲述了String的相关操作命令。本篇文章主要讲解Redis中数据结构Hash的相关操作命令。希望会对你有所帮助。 目录 一、Hash哈希 二、命令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET HLEN HSETNX HINCRBY 和 HINCRBYFLOAT 三、小结 &#x1f64b;‍♂️ 作者&a…

SpringBoot整合RabbitMQ的快速使用教程

目录 一、引入依赖 二、配置rabbitmq的连接信息等 1、生产者配置 2、消费者配置 三、设置消息转换器 四、生产者代码示例 1、配置交换机和队列信息 2、生产消息代码 五、消费者代码示例 1、消费层代码 2、业务层代码 在分布式系统中&#xff0c;消息队列是一种重要…