北京顺义做网站,河东做网站的公司,网站备案后打不开,成都市专业制作网站系列文章目录 提示#xff1a;这里可以添加系列文章的所有文章的目录#xff0c;目录需要自己手动添加 Spring Security之认证 提示#xff1a;写完文章后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是Spring…系列文章目录 提示这里可以添加系列文章的所有文章的目录目录需要自己手动添加 Spring Security之认证 提示写完文章后目录可以自动生成如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是Spring Security二、Spring Security之认证环境准备数据库认证自定义认证逻辑 PasswordEncoder自定义登录页面突破CSRF防护会话管理认证成功后的处理认证失败后的处理退出登录退出成功处理器Remember Me 总结 前言
提示这里可以添加本文要记录的大概内容
当涉及到构建安全的 Web 应用程序时Spring Security 是一个广受欢迎且功能强大的框架。它提供了一系列的特性和功能用于保护应用程序免受未经授权的访问。 在这篇博客中我们将深入探讨 Spring Security 的认证部分。认证是安全体系的第一道防线它确保只有经过身份验证的用户才能访问受保护的资源。 我们将从 Spring Security 的基础知识开始了解它的核心概念和组件。然后我们将逐步介绍如何使用 Spring Security 实现常见的认证方式如用户名和密码登录。 无论你是 Spring Security 的新手还是有一定经验的开发者这篇博客都将为你提供一个深入了解 Spring Security 认证的机会。通过掌握这些知识你将能够构建更安全、可靠的 Web 应用程序。 让我们一起开启 Spring Security 认证之旅保护我们的应用程序免受未经授权的访问 提示以下是本篇文章正文内容下面案例可供参考
一、什么是Spring Security
Spring Security 是一个用于保护 Spring 应用程序安全性的框架。它提供了一套全面的安全特性可以帮助开发人员轻松地构建安全的应用程序。Spring Security 的核心目标是提供一种易于使用、灵活且强大的方式来保护应用程序的安全性。 Spring Security 的主要功能包括身份验证、授权、密码加密、跨域安全性等。它支持多种认证方式如基本认证、摘要认证、JWT 认证等。同时Spring Security 还提供了强大的授权功能允许开发人员根据用户角色和权限来限制对特定资源的访问。 总的来说Spring Security 是一个非常有用的框架可以帮助开发人员轻松地构建安全的应用程序。
二、Spring Security之认证
认证就是判断用户身份是否合法如果合法就可以继续访问不合法就拒绝访问
环境准备
1.准备一个名为mysecurity的Mysql数据库 2.创建SpringBoot项目添加依赖
!-- SpringMVC --
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId
/dependency
!--Thymeleaf--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId
/dependency
!--Spring Security--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId
/dependency
!-- Mysql驱动 --
dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope
/dependency
!-- MyBatisPlus --
dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.0/version
/dependency
!-- lombok --
dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional
/dependency
!-- junit --
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope
/dependency
3.为SpringBoot项目编写配置文件
server:port: 80#日志格式
logging:pattern:console: %d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n# 数据源
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql:///mysecurity?serverTimezoneUTCusername: rootpassword: root
4.在template文件夹编写项目主页面main.html
!DOCTYPE html
html
headmeta charsetUTF-8title主页面/title
/head
body
h1主页面/h1
/body
/html
5.编写访问页面控制器
Controller
public class PageController {RequestMapping(/{page})public String showPage(PathVariable String page){return page;}
}
数据库认证
在实际的项目中用户通过输入用户名和密码待验证通过后即登录成功而用户信息大多保存在数据库中。而用户身份验证的这个过程我们称之为认证逻辑。 1.准备数据库数据用户信息数据都是保存在该数据库中
CREATE TABLE users (id int(11) NOT NULL AUTO_INCREMENT,username varchar(255),password varchar(255) ,phone varchar(255) ,PRIMARY KEY (id)
);INSERT INTO users VALUES (1, baizhan, baizhan, 13812345678);
INSERT INTO users VALUES (2, sxt, sxt, 13812345678);
2.编写用户实体类
Data
public class Users {private Integer id;private String username;private String password;private String phone;
}
3.编写dao接口
public interface UsersMapper extends BaseMapperUsers {
}
4.在 SpringBoot启动类中添加 MapperScan 注解扫描Mapper文件夹
SpringBootApplication
MapperScan(com.itbaizhan.myspringsecurity.mapper)
public class MysecurityApplication {public static void main(String[] args) {SpringApplication.run(MysecurityApplication.class, args);}
}
自定义认证逻辑
在实际项目中认证逻辑是需要自定义控制的。将 UserDetailsService 接口的实现类放入Spring容器即可自定义认证逻辑。UserDetailsService 的实现类必须重写 loadUserByUsername 方法该方法定义了具体的认证逻辑参数 username 是前端传来的用户名我们需要根据传来的用户名查询到该用户一般是从数据库查询并将查询到的用户封装成一个UserDetails对象该对象是Spring Security提供的用户对象包含用户名、密码、权限。Spring Security会根据UserDetails对象中的密码和客户端提供密码进行比较。相同则认证通过不相同则认证失败。
5.创建UserDetailsService的实现类编写自定义认证逻辑
Service
public class MyUserDetailsService implements UserDetailsService {Autowiredprivate UsersMapper usersMapper;// 自定义认证逻辑Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 1.构造查询条件QueryWrapperUsers wrapper new QueryWrapperUsers().eq(username, username);// 2.查询用户Users users usersMapper.selectOne(wrapper);// 3.封装为UserDetails对象UserDetails userDetails User.withUsername(users.getUsername()).password(users.getPassword()).authorities(admin).build();// 4.返回封装好的UserDetails对象return userDetails;}
}
PasswordEncoder
在实际的项目开发中我们往数据库的密码不会是明文密码而是经过我们加密后的密码。当用户传入的明文密码后SpringSecurity使用密码解析器将明文密码加密成密文密码然后再将数据库中的密文密码进行比对匹配成功则通过反之不通过。
创建SecurityConfig配置类添加SpringSecurity密码解析器(PasswordEncoder)
// Security配置类
Configuration
public class SecurityConfig {//密码编码器Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
自定义登录页面
SpringSecurity给我们提供了登录界面但是再实际的项目中登录页面都是用的自己的这样更能突出项目特色所以我们要自定义登录界面。 1.编写登录界面 2.在Spring Security配置类自定义登录页面
Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{//Spring Security配置Overrideprotected void configure(HttpSecurity http) throws Exception {// 自定义表单登录http.formLogin() .loginPage(/login.html) // 自定义登录页面.usernameParameter(username) // 表单中的用户名项.passwordParameter(password) // 表单中的密码项.loginProcessingUrl(/login) // 登录路径表单向该路径提交提交后自动执行UserDetailsService的方法.successForwardUrl(/main) //登录成功后跳转的路径.failureForwardUrl(/fail); //登录失败后跳转的路径// 需要认证的资源http.authorizeRequests().antMatchers(/login.html).permitAll() //登录页不需要认证.anyRequest().authenticated(); //其余所有请求都需要认证//关闭csrf防护http.csrf().disable();}Overridepublic void configure(WebSecurity web) throws Exception {// 静态资源放行web.ignoring().antMatchers(/css/**);}
}
突破CSRF防护
CSRF跨站请求伪造通过伪造用户请求访问受信任的站点从而进行非法请求访问是一种攻击手段。SpringSecurity默认开启CSRF防护这就限制了除了GET请求以外的大多数请求。我们可以通过关闭CSRF防护来解决问题但是这就不够安全了。CSRF为了保证不是其他第三方网站访问要求访问时携带参数名为_csrf值为令牌令牌在服务端产生如果携带的令牌和服务端的令牌匹配成功则正常访问。
form classform action/login methodpost!-- 在表单中添加令牌隐藏域 --input typehidden th:value${_csrf.token} name_csrf th:if${_csrf}/input typetext placeholder用户名 nameusernameinput typepassword placeholder密码 namepasswordbutton typesubmit登录/button
/form
会话管理
SpringSecurity提供了会话管理功能它将用户信息保存再会话中我们可以通过SecurityContext对象中获取用户信息。
RestController
public class MyController {// 获取当前登录用户名RequestMapping(/users/username)public String getUsername(){// 1.获取会话对象SecurityContext context SecurityContextHolder.getContext();// 2.获取认证对象Authentication authentication context.getAuthentication();// 3.获取登录用户信息UserDetails userDetails (UserDetails) authentication.getPrincipal();return userDetails.getUsername();}
}
认证成功后的处理
如果在认证成功后需要处理一些自定义的逻辑可以使用登陆成功处理器。 1.自定义登录成功处理器
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {// 拿到登录用户的信息UserDetails userDetails (UserDetails)authentication.getPrincipal();System.out.println(用户名:userDetails.getUsername());System.out.println(一些操作...);// 重定向到主页response.sendRedirect(/main);}
}
2.配置登录成功处理器
http.formLogin() // 使用表单登录.loginPage(/login.html) // 自定义登录页面.usernameParameter(username) // 表单中的用户名项.passwordParameter(password) // 表单中的密码项.loginProcessingUrl(/login) // 登录路径表单向该路径提交提交后自动执行UserDetailsService的方法// .successForwardUrl(/main) //登录成功后跳转的路径.successHandler(new MyLoginSuccessHandler()) //登录成功处理器.failureForwardUrl(/fail); //登录失败后跳转的路径
认证失败后的处理
如果在认证成功后需要处理一些自定义的逻辑可以使用登陆失败处理器。 1.自定义登录失败处理器
public class MyLoginFailureHandler implements AuthenticationFailureHandler {Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {System.out.println(记录失败日志...);response.sendRedirect(/fail);}
}
2.配置登录失败处理器
http.formLogin() // 使用表单登录.loginPage(/login.html) // 自定义登录页面.usernameParameter(username) // 表单中的用户名项.passwordParameter(password) // 表单中的密码项.loginProcessingUrl(/login) // 登录路径表单向该路径提交提交后自动执行UserDetailsService的方法// .successForwardUrl(/main) //登录成功后跳转的路径.successHandler(new MyLoginSuccessHandler()) //登录成功处理器// .failureForwardUrl(/fail) //登录失败后跳转的路径.failureHandler(new MyLoginFailureHandler()); //登录失败处理器// 需要认证的资源
http.authorizeRequests().antMatchers(/login.html).permitAll() // 登录页不需要认证.antMatchers(/fail).permitAll() // 失败页不需要认证.anyRequest().authenticated(); //其余所有请求都需要认证
退出登录
当用户退出后需要清楚认证状态、销毁HttpSession对象跳转登录界面
1.配置退出登录的路径和退出后跳转的路径
// 退出登录配置
http.logout().logoutUrl(/logout) // 退出登录路径.logoutSuccessUrl(/login.html) // 退出登录后跳转的路径.clearAuthentication(true) //清除认证状态默认为true.invalidateHttpSession(true); // 销毁HttpSession对象默认为true
2.在网页中添加退出登录超链接
!DOCTYPE html
html
headmeta charsetUTF-8title主页面/title
/head
body
h1主页面/h1
a href/logout退出登录/a
/body
/html
退出成功处理器
我们也可以自定义退出成功处理器在退出后清理一些数据写法如下
1.自定义退出成功处理器
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {System.out.println(清除一些数据...);response.sendRedirect(/login.html);}
}
2.配置退出成功处理器
// 退出登录配置
http.logout().logoutUrl(/logout) // 退出登录路径// .logoutSuccessUrl(/login.html) // 退出登录后跳转的路径.clearAuthentication(true) //清除认证状态默认为true.invalidateHttpSession(true) // 销毁HttpSession对象默认为 true.logoutSuccessHandler(new MyLogoutSuccessHandler()); //自定义退出成功处理器
Remember Me
SpringSecurity提供了“记住我”功能当使用记住我功能登陆后SpringSecurity会生成一个令牌令牌一方面保存在数据库里另一方面生成一个叫remember-me的Cookie保存到客户端。之后客户端访问项目时自动携带令牌不登录即可完成认证。
1.编写“记住我”配置类
Configuration
public class RememberMeConfig {Autowiredprivate DataSource dataSource;// 令牌RepositoryBeanpublic PersistentTokenRepository getPersistentTokenRepository() {// 为Spring Security自带的令牌控制器设置数据源JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl new JdbcTokenRepositoryImpl();jdbcTokenRepositoryImpl.setDataSource(dataSource);//自动建表第一次启动时需要第二次启动时注释掉
// jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);return jdbcTokenRepositoryImpl;}
}
2.修改Security配置类
// 记住我配置
http.rememberMe().userDetailsService(userDetailsService)//登录逻辑交给哪个对象.tokenRepository(repository) //持久层对象.tokenValiditySeconds(30); //保存时间单位秒
3.在登录页面添加“记住我”复选框
form classform action/login methodpostinput typetext placeholder用户名 nameusernameinput typepassword placeholder密码 namepasswordinput typecheckbox nameremember-me valuetrue/记住我/brbutton typesubmit登录/button
/form 总结
提示这里对文章进行总结
总的来说Spring Security 为我们提供了一个强大而灵活的框架来保护应用程序的安全性。通过理解和应用所学的知识我们可以构建更安全、可靠的 Web 应用程序。 希望这篇博客对你有所帮助让你对 Spring Security 的认证有了更深入的了解。如果你有任何进一步的问题或想要深入探讨其他安全相关主题请随时留言