spring boot 整合 spring security

项目结构

添加依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEASE</version><relativePath/></parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId><version>2.4.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

修改配置文件

spring:freemarker:template-loader-path: classpath:/templates/charset: UTF-8cache: falsesuffix: .ftl

创建登录页

login.ftl

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页</title>
</head>
<body>
<form id="formLogin" method="post">用户名<input type="text" name="username" value="admin"/>密码<input type="text" name="password" value="123456"/><input type="checkbox" name="remember-me" value="true"/>记住我<input type="button" onclick="login()" value="login"/>
</form>
</body>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script>function login() {$.ajax({type: "POST",//方法类型dataType: "json",//服务器预期返回类型url: "/login",   // 登录urldata: $("#formLogin").serialize(),success: function (data) {console.log(data)if (data.code == 200) {window.location.href = "/";} else {alert(data.message);}}});}
</script>
</html>

创建首页

index.ftl

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>
我是首页
</body>
</html>

创建SecurityConfiguration类

package com.lgg.config;import com.lgg.service.MyAuthenticationService;
import com.lgg.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;/*** Security配置类*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate MyAuthenticationService myAuthenticationService;/*** http请求处理方法** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/toLoginPage", "/code/**").permitAll()//放行登录页面.anyRequest().authenticated()//所有请求都需要登录认证才能访问;.and().formLogin()//开启表单认证.loginPage("/toLoginPage")//自定义登录页面.loginProcessingUrl("/login")// 登录处理Url.usernameParameter("username").passwordParameter("password") //修改自定义表单name值..successHandler(myAuthenticationService)//自定义登录成功处理.failureHandler(myAuthenticationService)//自定义登录失败处理
//                .defaultSuccessUrl("/")
//                .successForwardUrl("/").and().logout().logoutUrl("/logout")//设置退出url.logoutSuccessHandler(myAuthenticationService)//自定义退出处理.and().rememberMe().rememberMeParameter("remember-me")// 自定义表单name值.tokenValiditySeconds(2 * 7 * 24 * 60 * 60)// 两周.tokenRepository(getPersistentTokenRepository())// 设置tokenRepository.and().csrf().disable(); // 关闭csrf防护// 允许iframe加载页面http.headers().frameOptions().sameOrigin();}@AutowiredDataSource dataSource;/*** 持久化token,负责token与数据库之间的相关操作** @return*/@Beanpublic PersistentTokenRepository getPersistentTokenRepository() {JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);//设置数据源// 启动时创建一张表, 第一次启动的时候创建, 第二次启动的时候需要注释掉, 否则会报错
//        tokenRepository.setCreateTableOnStartup(true);return tokenRepository;}/*** WebSecurity** @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) throws Exception {//解决静态资源被拦截的问题web.ignoring().antMatchers("/css/**", "/images/**", "/js/**", "/favicon.ico");}/*** 身份验证管理器** @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailsService);// 使用自定义用户认证}}

创建MyAuthenticationService类

package com.lgg.service;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** 自定义登录成功或失败处理类*/
@Service
public class MyAuthenticationService implements AuthenticationSuccessHandler, AuthenticationFailureHandler, LogoutSuccessHandler {@AutowiredObjectMapper objectMapper;private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {System.out.println("登录成功后续处理....");
//        redirectStrategy.sendRedirect(request, response, "/");
//
        Map result = new HashMap();
        result.put("code", HttpStatus.OK.value());// 设置响应码
        result.put("message", "登录成功");// 设置响应信息
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(result));}@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {System.out.println("登录失败后续处理....");//redirectStrategy.sendRedirect(request, response, "/toLoginPage");
//        Map result = new HashMap();
//        result.put("code", HttpStatus.UNAUTHORIZED.value());// 设置响应码
//        result.put("message", exception.getMessage());// 设置错误信息
//        response.setContentType("application/json;charset=UTF-8");
//        response.getWriter().write(objectMapper.writeValueAsString(result));}@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {System.out.println("退出成功后续处理....");redirectStrategy.sendRedirect(request, response, "/toLoginPage");}}

创建MyUserDetailsService类

package com.lgg.service;import com.lgg.entity.User;
import com.lgg.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.Service;import java.util.ArrayList;
import java.util.Collection;/*** 基于数据库中完成认证*/
@Service
public class MyUserDetailsService implements UserDetailsService {@AutowiredUserService userService;/*** 根据username查询用户实体** @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userService.findByUsername(username);if (user == null) {throw new UsernameNotFoundException(username);// 用户名没有找到}// 先声明一个权限集合, 因为构造方法里面不能传入nullCollection<? extends GrantedAuthority> authorities = new ArrayList<>();// 需要返回一个SpringSecurity的UserDetails对象UserDetails userDetails =new org.springframework.security.core.userdetails.User(user.getUsername(),
//                        "{noop}" + user.getPassword(),// {noop}表示不加密认证。"{bcrypt}" + user.getPassword(),true, // 用户是否启用 true 代表启用true,// 用户是否过期 true 代表未过期true,// 用户凭据是否过期 true 代表未过期true,// 用户是否锁定 true 代表未锁定authorities);return userDetails;}
}

创建HelloSecurityController类

package com.lgg.controller;import com.lgg.entity.User;
import com.lgg.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;/*** security入门案例*/
@Controller
public class HelloSecurityController {@RequestMapping("/toLoginPage")public String toLoginPage() {return "login";}/*** 获取当前登录用户** @return*/@RequestMapping("/abc")
//    @ResponseBodypublic String getCurrentUser() {UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();System.out.println("abc");return "abc";}/*** 获取当前登录用户** @return*/@RequestMapping("/loginUser1")@ResponseBodypublic UserDetails getCurrentUser1() {UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();return userDetails;}/*** 获取当前登录用户** @return*/@RequestMapping("/loginUser2")@ResponseBodypublic UserDetails getCurrentUser(Authentication authentication) {UserDetails userDetails = (UserDetails) authentication.getPrincipal();return userDetails;}/*** 获取当前登录用户** @return*/@RequestMapping("/loginUser3")@ResponseBodypublic UserDetails getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {return userDetails;}@Autowiredprivate UserService userService;/*** 根据用户ID查询用户** @return*/@GetMapping("/{id}")@ResponseBodypublic User getById(@PathVariable Integer id) {//获取认证信息Authentication authentication = SecurityContextHolder.getContext().getAuthentication();// 判断认证信息是否来源于RememberMeif (RememberMeAuthenticationToken.class.isAssignableFrom(authentication.getClass())) {throw new RememberMeAuthenticationException("认证信息来源于RememberMe,请重新登录");}User user = userService.getById(id);return user;}}

启动项目验证

访问任意接口,都会被路由到登录页面login.ftl,只有登录成功后,才能正常访问其他接口。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UiPath:人工智能和重新加速增长是 2024 年的好兆头

UiPath&#xff08;NYSE&#xff1a;PATH&#xff09;重新加速增长&#xff0c;同时在销售和营销方面变得最高效&#xff0c;使其成为进入 2024 年的有吸引力的成长型股票。 UiPath 最初被归类为机器人流程自动化 (RPA) 公司&#xff0c;现在认为自己是一家人工智能驱动的自动…

MATLAB R2022b 安装

文章用于学习记录 文章目录 前言下载解压安装包总结 前言 下载解压安装包 MATLAB R2022b —— A9z3 装载(Mount) MATLAB_R2022b_Win64.iso 打开装载好的 DVD 驱动器并找到 setup&#xff0c;单击鼠标右键以管理员身份运行&#xff1a; 点击窗口右上角的 高级选项下拉框&#…

【UGUI】Unity为下拉菜单添加选项(DropDown)

要想控制谁就把谁拿到代码里-获取组件-修改组件参数&#xff08;变量或者方法&#xff09; 代码示例&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro;public class UIcontrol : MonoBehavi…

贝叶斯网络 (期末复习)

文章目录 贝叶斯网络&#xff08;概率图模型&#xff09;定义主要考点例题- 要求画出贝叶斯网络图- 计算各节点的条件概率表- 计算概率-分析独立性 贝叶斯网络&#xff08;概率图模型&#xff09; 定义 一种简单的用于表示变量之间条件独立性的有向无环图&#xff08;DAG&…

一线大厂Redis高并发缓存架构(待完善)

场景1&#xff1a;秒杀库存场景&#xff0c; 10000人抢100个商品 如果用普通的分布式锁实现&#xff0c; 最后抢到的人&#xff0c;要等前面99个人抢完 优化方案&#xff1a;可用分段锁&#xff0c; 降低锁的粒度&#xff0c; 比如1-10库存用锁product:101_1,11-20库存用锁pr…

MySQL -DDL 及表类型

DDL 创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specification:[DEFAULT] CHARACTER SET charset_name [DEFAULT] COLLATE collation_name 1.CHARACTER SET&#xff1a…

PT读spef报PARA-006如何解决?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 There are multiple causes that can trigger PARA-006 errors. Here is a checklist. 1) SPEF reading order Functionally, the parasitic files can be read in any order. For best stitching…

acwing算法基础之动态规划--数位统计DP、状态压缩DP、树形DP和记忆化搜索

目录 1 基础知识2 模板3 工程化 1 基础知识 暂无。。。 2 模板 暂无。。。 3 工程化 题目1&#xff1a;求a~b中数字0、数字1、…、数字9出现的次数。 思路&#xff1a;先计算1~a中每位数字出现的次数&#xff0c;然后计算1~b-1中每位数字出现的次数&#xff0c;两个相减即…

C++基础 -29- 友元类

友元类格式 friend class person2;类的友元类访问类的全部成员 #include "iostream"using namespace std;class person1 { public:int a;protected:int b;private:int c;friend class person2; };class person2 { public:void test(){person1 a;a.a 100;a.b 200…

校园局域网规划与设计(cisco仿真模拟)

摘 要 随着网络技术的发展&#xff0c;校园网的建设已经进入到一个蓬勃发展的阶段。校园网的建成和使用&#xff0c;对于提高教学和科研的质量、改善教学和科研条件、加快学校的信息化进程&#xff0c;开展多媒体教学与研究以及使教学多出人才、科研多出成果有着十分重要而深远…

05-建造者模式-C语言实现

UML类图&#xff1a; 代码实现&#xff1a; #include <stdio.h> #include <stdlib.h>// 产品类 typedef struct {char* part1;char* part2;char* part3; } Product;// 抽象建造者类 typedef struct {void (*buildPart1)(void*, const char*);void (*buildPart2)(v…

leetCode 494.递增子序列 + 回溯算法 + 图解 + 笔记

给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况。 示例 1&#…

Python项目管理利器poetry我愿称之为神!

MongoDB是一种流行的NoSQL数据库&#xff0c;它以灵活的文档结构存储数据。MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包&#xff0c;你可以从MongoDB官网下载安装&#xff0c;MongoDB 预编译二进制包下载地址&#xff1a; https://www.mongodb.com/try/download/…

【Linux】信号概念和信号的产生

文章目录 一、什么是信号&#xff1f;1.signal系统调用2.从硬件解析键盘数据如何输入给内核3.同步和异步 二、信号的产生1.键盘组合键2. kill命令3.系统调用接口3.1kill3.2 raise3.3abort 4.异常5.软件条件 重谈core dump标志位 一、什么是信号&#xff1f; 以日常为例&#x…

Elasticsearch:么是向量嵌入?

向量嵌入定义 向量嵌入 (vector embeddings) 是一种将单词、句子和其他数据转换为捕获其含义和关系的数字的方法。 它们将不同的数据类型表示为多维空间中的点&#xff0c;其中相似的数据点更紧密地聚集在一起。 这些数字表示可以帮助机器更有效地理解和处理这些数据。 单词和…

VS安装QT VS Tools编译无法通过

场景&#xff1a; 项目拷贝到虚拟机内部后&#xff0c;配置好相关环境后无法编译&#xff0c;安装QT VS Tools后依旧无法编译&#xff0c;查找资料网上说的是QT工具版本不一致导致的&#xff0c;但反复试了几个版本后依旧无法编译通过。错误信息如下&#xff1a; C:\Users\Ad…

OpenTelemetry系列 - 第1篇 相关概念

目录 一、背景二、概念2.1 Traces & Span2.2 Metrics2.3 Logs2.4 Baggage2.5 OTel2.6 OTLP2.7 Resources2.8 Instrumentation Scope2.9 Sampling 三、核心组件 一、背景 OpenTelemetry是一个可观察性框架和工具包&#xff0c;旨在创建和管理遥测数据&#xff0c;如跟踪、指…

Monocle 3 | 太牛了!单细胞必学R包!~(五)(差异分析之聚类比较与模块鉴定)

1写在前面 准备出去玩耍了&#xff0c;今天就不废话了&#xff0c;直接上主题吧。&#x1f973; monocle3做差异分析也是牛的一米&#xff01;~&#x1f33e; 2用到的包 rm(list ls())library(tidyverse)library(monocle3) 3示例数据 我们还是载入之前用过的一个数据集吧。&am…

HarmonyOs 4 (三) ArkTS语言

目录 一 认识ArkTs语言1.1 ArkTs1.2 基本结构 二 基本语法2.1 声明式UI2.1.1 创建组件2.1.1.1 无参数2.1.1.2 有参数2.1.1.3 组件样式2.1.1.4 组件方法2.1.1.5 组件嵌套 2.1.2 自定义组件2.1.2.1 基本结构2.1.2.2 成员函数/变量2.1.2.3 自定义组件的参数规定2.1.2.4 Build函数2…

高效转码工具Compressor for Mac,让视频处理更轻松

在现如今的数字时代&#xff0c;视频内容已经成为人们生活中不可或缺的一部分。无论是在社交媒体上分享生活点滴&#xff0c;还是在工作中制作专业的营销视频&#xff0c;我们都希望能够以高质量、高效率地处理和传输视频文件。而Compressor for Mac作为一款强大的视频转码工具…