Spring Security-2-表单认证
我们在地址小节介绍了Spring Security的HttpBasic基础认证模式,这个模式方法比较简单,不需要制作登录页面,使用范围较小。如果我们在一个完整的系统里面,登录页面也许我们自己设计,并且提供多种登录方式。这就需要使用Spring Security为我们提供的表单登录进行登录认证
项目代码准备
Controller层代码
@Controller public class TestController { /** * 登录 * @return */ @RequestMapping("/login/page") public String toLogin() { return "login"; // classpath: /templates/login.html } // 首页 @RequestMapping({"/index", "/", ""}) public String index() { return "index"; } // 日志管理 @GetMapping("/syslog") @ResponseBody public String showOrder() { return "springboot葵花宝典 syslog"; } // 用户管理 @GetMapping("/sysuser") @ResponseBody public String addOrder() { return "springboot葵花宝典 sysuser"; } }
index.html
我们设置一个简单的index.html页面,代码如下
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8" /> <title>springboot葵花宝典管理系统</title> </head> <body> <h1>springboot葵花宝典管理系统</h1> <br> <a href="/syslog">日志管理</a> <br> <a href="/sysuser">用户管理</a>
启动浏览器输入http://localhost:8888/,显示页面如下
如果我们想在页面的时候添加登录页面和权限,那么我们要实现以下步骤。
添加Spring Security启动依赖
要在我们创建项目的pom.xml
中添加spring-boot-starter-security
依赖
<!--spring security--> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.6.4</version> </dependency>
创建LearnSrpingSecurity安全配置类
LearnSrpingSecurity
安全配置类作为我们的安全控制中心,具体实现步骤如下:
创建LearnSrpingSecurity类在config包下
让LearnSrpingSecurity继承WebSecurityConfigurerAdapter
在LearnSrpingSecurity类上添加@EnableWebSecurity注解
重写以下两个方法
configure(AuthenticationManagerBuilder auth) 认证管理器
认证信息提供方式(用户名、密码、当前用户的资源权限)
可采用内存存储方式,也可能采用数据库方式等
configure(HttpSecurity http) 资源权限配置(过滤器链)
被拦截资源
资源对应的权限
认证方式:httpbasic、httpform
定制登录页面、登录请求地址,以及成功和失败处理方式
自定义 spring security 过滤器
/** * 安全配置类 */ @EnableWebSecurity public class LearnSrpingSecurity extends WebSecurityConfigurerAdapter { /** * 认证管理器 * 1.认证信息提供方式(用户名、密码、当前用户的资源权限) * 2.可采用内存存储方式,也可能采用数据库方式等 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { super.configure(auth); } /** * 资源权限配置(过滤器链): * 1、被拦截的资源 * 2、资源所对应的角色权限 * 3、定义认证方式:httpBasic 、httpForm * 4、定制登录页面、登录请求地址、错误处理方式 * 5、自定义 spring security 过滤器 * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin()//表单认证 .and() .authorizeRequests() .anyRequest().authenticated(); } }
现在我们启动程序并输入http://localhost:8080/我们发现页面像httpbasic一样自动跳转到了http://localhost:8080/login,用户名和密码还是像之前一样
- 用户名默认 user
- 密码 自动生成
输入用户和密码后就看显示原来的页面信息
@EnableSecurity注解解释
我们添加@EnableWebSecurity注解是为了让LearnSrpingSecurity类被Spring发现并进行注册,为什么添加上这个注解就会被Spring发现并注册呢?,我们查看@EnableWebSecurity源码发现,EnableWebSecurity注解标注了@Configuration注解
@Configuration public @interface EnableWebSecurity { boolean debug() default false; }
用户角色配置
如果我们需要自定义用户和密码,可以在configure(AuthenticationManagerBuilder auth) 认证管理器中进行实现,提供了内存和数据库等存储用户信息的方式,具体代码实现如下
内存管理用户信息
@Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } /** * 认证管理器 * 1.认证信息提供方式(用户名、密码、当前用户的资源权限) * 2.可采用内存存储方式,也可能采用数据库方式等 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //super.configure(auth); auth.inMemoryAuthentication() .withUser("admin") .password(passwordEncoder().encode("123456")) .roles("admin") .authorities("Role_admin") .and() .passwordEncoder(passwordEncoder());//配置BCrypt加密 }
inMemoryAuthentication:使用内存存储用户信息
withUser:设置用户名
password:设置用户密码,在设置密码的时候必须注入PasswordEncoder
authorities: 是对应用户拥有资源ID对应的资源访问的的权限
roles:方法用于指定用户的角色,一个用户可以有多个角色
现在我们启动程序并输入http://localhost:8080/,页面还是会自动跳转到http://localhost:8888/login,输入我们自定的用户名和密码
自定义登录页面
当我们设置了用户名和密码以后,我们肯定还想设置一个自己的登录页面,我们需要将自定义登录页面需要放置在src\main\resources\static文件夹下,我们将登录页面命名为myLogin.html代码如下
<!--suppress ALL--> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>springboot葵花宝典登录页面</title> <!-- Tell the browser to be responsive to screen width --> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>springboot葵花宝典登录页面</h1> <form th:action="@{/login/form}" action="index.html" method="post"> <span>用户名称</span><input type="text" name="username" /> <br> <span>用户密码</span><input type="password" name="password" /> <br> <div th:if="${param.error}"> <span th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}" style="color:#ff0000">用户名或 密码错误</span> </div> <input type="submit" value="登陆"> </form> </body> </html>
在configure(HttpSecurity http)自定义表单的配置
设置自定义登录页面以后,我们需要在configure(HttpSecurity http)设置相对应的配置
/** * 资源权限配置(过滤器链): * 1、被拦截的资源 * 2、资源所对应的角色权限 * 3、定义认证方式:httpBasic 、httpForm * 4、定制登录页面、登录请求地址、错误处理方式 * 5、自定义 spring security 过滤器 * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() //禁用跨站csrf攻击防御,后面的章节会专门讲解 .formLogin() .loginPage("/login/page")//用户的请求没有权限就跳转到登录页面 .loginProcessingUrl("/login/form")//登录表单form中action的地址,也就是处理认证请求的路径 .usernameParameter("username")///登录表单form中用户名输入框input的name名,不修改的话默认是username .passwordParameter("password")//form中密码输入框input的name名,不修改的话默认是password .and() .authorizeRequests() .antMatchers("/login/page").permitAll()//不需要通过登录验证就可以被访问的资源路径 .anyRequest().authenticated(); }
重启程序,再次访问localhost:8080,页面还是会自动跳转到http://localhost:8888/login,如图所示
mylogin.html页面中form表单中字段和configure(HttpSecurity http)配置的对应关系
登录页面显示提示信息
当提交登录form认证失败的时候,通过http://localhost:8888/login/page?error进行重新定向登录页面,此时地址带有error
参数,表示认证失败,默认情况下,提示信息为英文,但是也可以配置成中文
实现中文提示信息
在spring-security-core-x.x.x.jar下有国际化配置文件messages_xx.properties
默认ReloadableResourceBundleMessageSource加载了message.properties英文配置文件
手动实现加载指定messages_zh_CN.properties中文配置文件
在config包下创建SecurityMessageConfig
@Configuration public class SecurityMessageConfig { @Bean // 加载中文的认证提示信息 public ReloadableResourceBundleMessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); //.properties 不要加到后面 messageSource.setBasename("classpath:org/springframework/security/messages_zh_CN"); return messageSource; } }
测试
重新启动项目,输入错误的用户信息,显示错误为用户或密码错误
如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!