# springSecurity **Repository Path**: javawcj/spring-security ## Basic Information - **Project Name**: springSecurity - **Description**: 包含 Spring Security 安全框架的基础知识,认证、授权、安全过滤器链等内容,并提供了案例代码和实践练习,方便学习和掌握 Spring Security 的使用方法。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-13 - **Last Updated**: 2023-06-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SpringSecurity 在web开发中,安全第一!过滤取、拦截器等 功能性需求:否 做网站:安全应该在什么时候考虑? - 漏洞,隐私泄漏~ - 架构一旦确定 - shoiro、SpringSecurity:很像,除了类不一样,名字不一样; 认证,授权(vip1、vip2、vip3) Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。 Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正威力在于它可以多么容易地扩展以满足自定义需求 - 功能权限 - 访问权限 - 菜单权限 - 之前拦截器、过滤器,但是需要大量的代码 ## 环境搭建 - 创建boot项目 - 引入前段代码和依赖 ``` org.springframework.boot spring-boot-starter-web org.thymeleaf thymeleaf-spring5 org.thymeleaf.extras thymeleaf-extras-java8time ``` ![](img/WechatIMG16.png) - 编写controller ``` package com.wcj.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class RouterController { @RequestMapping({"/","index"}) public String index(){ return "index"; } @RequestMapping("toLogin") public String toLogin(){ return "views/login"; } @RequestMapping("level1/{id}") public String level1(@PathVariable("id") int id){ return "views/level1" + id; } @RequestMapping("level2/{id}") public String level2(@PathVariable("id") int id){ return "views/level2" + id; } @RequestMapping("level3/{id}") public String level3(@PathVariable("id") int id){ return "views/level3" + id; } } ``` - 启动boot项目,访问localhost:8080 ![](img/WechatIMG17.png) - 如上图进入主页,在没有做安全控制的情况下可以访问任意资源 ![](img/WechatIMG18.png) - 登陆界面 ![](img/WechatIMG19.png) ## 简介 Spring Security是针对Spring项目的安全框架,也是spring boot底层安全模块默认的技术选型,他可以实现强大的web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理 记住几个类: - WebSecurityConfigurerAdapter:自定义Security策略 - AuthenticationManagerBuilder:自定义认证策略 - @EnablWebSecurity:开启WebSceurity模式 spring Security的两个主要目标是“认证”和“授权” “认证”(Authentication) “授权”(Authorization) 这个概念是通用的,而不是只在Spring Security中存在 [参考官网](https://spring.io/projects/spring-security) [查看我们自己项目中的版本找到对应的帮助文档](https://docs.spring.io/spring-security/site/docs/5.2.0.RELEASE/reference/htmlsingle) ## 使用SpringSecurity - 导入SpringSecurity依赖 ``` org.springframework.boot spring-boot-starter-security ``` ![](img/aop.png) aop思想 - 配置Sceurity ``` @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { //授权 @Override protected void configure(HttpSecurity http) throws Exception { //首页所有人可以访问,功能页只有对应有权限的人才能访问 http.authorizeRequests()//认证一些请求 .antMatchers("/")//认证哪些请求 .permitAll()//哪些人可以访问(这里是所有人all) .antMatchers("/level1/**")//可以配置多个认证请求 .hasRole("vip1")//哪些人可以访问(这里只有vip1这个角色可以访问) .antMatchers("/level2/**")//可以配置多个认证请求 .hasRole("vip2")//哪些人可以访问(这里只有vip2这个角色可以访问) .antMatchers("/level3/**")//可以配置多个认证请求 .hasRole("vip3");//哪些人可以访问(这里只有vip3这个角色可以访问) } } ``` ![](img/http.png) 继承WebSecurityConfigurerAdapter 重写configure(HttpSecurity http)方法 添加@EnableWebSecurity - 浏览器访问资源测试 ![](img/WechatIMG20.png) 这时首页可以访问,而功能页面需要特定的权限 ### 配置自动跳转到登陆页面 ``` //没有权限默认回跳转到登陆页面,开启登陆页面 http.formLogin(); ``` 这时点击功能页面会自动跳转到登陆页面 ![](img/WechatIMG21.png) ### 绑定登陆用户 ``` //认证,(springboot 2.2.x 可以直接使用) @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //可以从数据库和内存中认证,这里我们使用内存中认证(这些数据正常从数据库中读取) auth.inMemoryAuthentication() .withUser("admin").password("123456").roles("vip1","cip2") .and() .withUser("root").password("root").roles("vip1","cip2","vip3"); //... //通过and()可以无限添加用户 } ``` 重写configure(AuthenticationManagerBuilder auth) 登陆测试发现报错代码500服务器错误:密码没有编码即没有加密 ![](img/WechatIMG22.png) 解决方式: 在springSecurity 5.0+ 中新增了很多加密方式 ``` //认证,(springboot 2.2.x 可以直接使用) @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //可以从数据库和内存中认证,这里我们使用内存中认证(这些数据正常从数据库中读取) auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","cip2") .and() .withUser("root").password(new BCryptPasswordEncoder().encode("root")).roles("vip1","cip2","vip3"); //... //通过and()可以无限添加用户 } ``` ### 注销用户 ``` //开启注销功能,如果注销成功自动跳转到首页 //http.logout().logoutUrl("/"); http.logout().logoutSuccessUrl("/"); ``` 浏览器访问资源测试: 注销用户后进入首页访问功能页面则需要重新登陆 ### 完善用户登陆权限 首页显示用户信息及登陆状态: 导入整合包: ``` org.thymeleaf.extras thymeleaf-extras-springsecurity4 3.0.4.RELEASE ``` 页面代码: ```
注销
``` 测试时发现功能没有生效? 原因:Springboot版本太高,当前使用版本是2.2.1该版本不支持,最高支持2.0.9 注意:降低版本后页面或java代码一些功能实现可能会发生变化。再次测试时关闭csrf或者使用POST方式 (防止网站攻击) 因为登出功能是通过GET方式请求的(即GET请求方式因为明文传输可能会让网站受到攻击) ``` //关闭csrf http.csrf().disable(); ``` #### 动态功能菜单的实现 基于上面的依赖场景 页面代码: ```
``` ### 开启记住我功能 ``` //开启记住我功能 http.rememberMe(); ``` 底层cookie实现 ### 定制登陆页面 ``` //没有权限默认回跳转到登陆页面 http.formLogin().loginPage("/toLogin") .usernameParameter("user") .passwordParameter("pwd") .loginProcessingUrl("login"); //开启记住我功能 http.rememberMe() .rememberMeParameter("remember");//自定义前端的参数 ``` 页面代码: ``` 记住我 ``` ## 自动跳转登陆页面原理 ``` The most basic configuration defaults to automatically generating a login page at the URL "/login", redirecting to "/login?error" for authentication failure. The details of the login page can be found on FormLoginConfigurer.loginPage(String) ``` 指定支持基于表单的身份验证。如果未指定FormLoginConfigurer.loginPage(String),则将生成默认登录页面。 配置示例: 最基本的配置默认为在URL“/login”处自动生成登录页面,如果身份验证失败,则重定向到“/login?error”。登录页面的详细信息可以在FormLoginConfigurer.loginPage(String)上找到 ``` @Configuration @EnableWebSecurity public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); } } The configuration below demonstrates customizing the defaults. @Configuration @EnableWebSecurity public class FormLoginSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin() .usernameParameter("username") // default is username .passwordParameter("password") // default is password .loginPage("/authentication/login") // default is /login with an HTTP get .failureUrl("/authentication/login?failed") // default is /login?error .loginProcessingUrl("/authentication/login/process"); // default is /login // with an HTTP // post } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); } } 返回值: the FormLoginConfigurer for further customizations 抛出: Exception 请参阅: FormLoginConfigurer.loginPage(String) ``` ## 用户注销原理 提供注销支持。这是在使用WebSecurityConfigurerAdapter时自动应用的。默认情况下,访问URL“/logoout”将使HTTP会话无效,清除已配置的任何rememberMe()身份验证,清除SecurityContextHolder,然后重定向到“/login?success”,从而将用户注销。 自定义配置示例 调用URL“/custom logout”时要注销的以下自定义项。注销将删除名为“remove”的cookie,不会使HttpSession无效,清除SecurityContextHolder,并在完成后重定向到“/logoout success”。 ``` @Configuration @EnableWebSecurity public class LogoutSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin() .and() // sample logout customization .logout().deleteCookies("remove").invalidateHttpSession(false) .logoutUrl("/custom-logout").logoutSuccessUrl("/logout-success"); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); } } 返回值: the LogoutConfigurer for further customizations 抛出: Exception ```