1.导入thymeleaf页面
首先导入jar,在pom.xml文件中添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在application.properties中添加配置:
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.mode=HTML
spring.thymeleaf.cache=false
最后在templates目录下添加需要用到的界面:
新增controller:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Controller
public class KongfuController{
private final String PREFIX = "pages/";
@GetMapping("/")
public String index(){
return "welcome";
}
@GetMapping("/userLogin")
public String loginPage(){
return PREFIX + "login";
}
@GetMapping("/level1/{path}")
public String level1(@PathVariable("path") String path){
return PREFIX + "level1/" + path;
}
@GetMapping("/level2/{path}")
public String level2(@PathVariable("path") String path){
return PREFIX + "level2/" + path;
}
@GetMapping("/level3/{path}")
public String level3(@PathVariable("path") String path){
return PREFIX + "level3/" + path;
}
}
运行application后,访问http://localhost:8080,就可以看到welcome.html在的内容了
哪有这么容易,这一步搞了好久,就是这么都找不到头绪,最后原因可能是因为我在idea环境准备好之前去新建了这个controller,导致没把它当成java的class去编译,删掉重新建才成功的
2.使用Security
导包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
编写web安全验证类
1.使用@EnableWebSecurity注解
2.继承WebSecurityConfigurerAdapter
3.重写configure(HttpSecurity http),对请求验证规则进行配置
4.重写configure(AuthenticationManagerBuilder auth) ,定义验证的账号和密码,目前只保存在内存中
代码:
package com.example.demo.config;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception{
//定制请求的授权规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("VIP1")
.antMatchers("/level2/**").hasRole("VIP2")
.antMatchers("/level3/**").hasRole("VIP3");
//开启自动配置的登陆功能
http.formLogin();
//开启自动配置的注销功能
//1、/logout注销
//2、注销成功,默认重定向到/login?logout,logoutSuccessUrl方法重写,这里把它指向了首页
http.logout().logoutSuccessUrl("/");
//开启记住我功能
//1、登陆成功后,保存登陆信息到浏览器cookie中
//2、点击注销会删除这个cookie
http.rememberMe();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
//定制认证规则
auth.inMemoryAuthentication()
.withUser("za").password("123456").roles("VIP1")
.and()
.withUser("zx").password("123456").roles("VIP1","VIP2")
.and()
.withUser("zs").password("123456").roles("VIP1","VIP2","VIP3");
}
}
访问http://localhost:8080/login,这是Security自带的login页面
测试使用这些定义的账号密码,发现无法登录,提示未定义的“null”用户
原因是,在2.0的springboot中,对明文的用户名和密码做了编码处理,因此还需要另外编写一个Encoder:
package com.example.demo.config;
import org.springframework.security.crypto.password.PasswordEncoder;
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
}
MySecurityConfig中的configure(AuthenticationManagerBuilder auth)应改为:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
//定制认证规则
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
.withUser("za").password("123456").roles("VIP1")
.and()
.withUser("zx").password("123456").roles("VIP1","VIP2")
.and()
.withUser("zs").password("123456").roles("VIP1","VIP2","VIP3");
}
再次登录,成功!
3.Thymeleaf使用Security
导包:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
首页welcome.html,在html标签中添加 xmlns:sec=“https://www.thymeleaf.org/thymeleaf-extras-springsecurity5”
1.sec:authorize=“isAuthenticated()”,未验证登录,提示游客登录
2.sec:authentication=“name”、sec:authentication=“principal.authorities”,完成验证登录,提示登录用户名和角色信息
3.sec:authorize=“hasRole(‘VIP1’)”,根据角色信息来展示“武功秘籍”
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>武林秘籍</title>
</head>
<body>
<h1 align="center">欢迎来到武林秘籍管理系统</h1>
<div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">
<h2 align="center"><span sec:authentication="name"></span>,你好,你的角色有:
<span sec:authentication="principal.authorities"></span>
</h2>
<div>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="注销">
</form>
</div>
</div>
<div sec:authorize="!isAuthenticated()">
<h2 align="center">游客你好,请<a th:href="@{/userLogin}">登录</a>查看秘籍内容</h2>
</div>
<div sec:authorize="hasRole('VIP1')">
<h3>普通</h3>
<ul>
<li><a th:href="@{/level1/1}">罗汉拳</a></li>
<li><a th:href="@{/level1/2}">武当剑</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP2')">
<h3>高级</h3>
<ul>
<li><a th:href="@{/level2/1}">太极拳</a></li>
<li><a th:href="@{/level2/2}">纵云梯</a></li>
</ul>
</div>
<div sec:authorize="hasRole('VIP3')">
<h3>绝世</h3>
<ul>
<li><a th:href="@{/level3/1}">葵花宝典</a></li>
<li><a th:href="@{/level3/2}">独孤九剑</a></li>
</ul>
</div>
</body>
</html>
4.自定义登录页面
在开始的controller中,定义了一个userLogin,现在把它作为登录界面
1.重写login.html:
<html lang="en"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>登陆页</title>
</head>
<body>
<div class="container">
<form class="form-signin" method="post" action="/userLogin">
<h2 class="form-signin-heading">请登录</h2>
<p>
<label for="username" class="sr-only">用户名</label>
<input type="text" id="username" name="user" class="form-control" placeholder="Username" required="" autofocus="">
</p>
<p>
<label for="password" class="sr-only">密码</label>
<input type="password" id="password" name="pwd" class="form-control" placeholder="Password" required="">
</p>
<p><input type="checkbox" name="remember"> Remember me on this computer.</p>
<input name="_csrf" type="hidden" value="26c20555-5ee2-4458-851f-0bb0d3530957">
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
</body></html>
这里我就是把Security自带的页面拷贝下来而已,把username输入框name改成了user,password输入框name输入框改成了pwd,把“记住我”的勾选框名称改成了remember,最后把表单提交的action改为/userLogin。
现在可以在configure(HttpSecurity http)方法中http自定义登陆界面信息:
@Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf().disable();
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("VIP1")
.antMatchers("/level2/**").hasRole("VIP2")
.antMatchers("/level3/**").hasRole("VIP3");
// usernameParameter修改获取用户名的name
// passwordParameter修改获取密码的name
// loginPage修改处理登录的方法
http.formLogin().usernameParameter("user").passwordParameter("pwd")
.loginPage("/userLogin");
http.logout().logoutSuccessUrl("/");
http.rememberMe().rememberMeParameter("remember");
}
还没有成功,使用自定义的登录界面登录,发现点击登陆按钮后,发生 403 Forbidden 错误
查找资料后发现,是因为拷贝过来的页面中,包含了Springboot的跨域信息:
<input name="_csrf" type="hidden" value="26c20555-5ee2-4458-851f-0bb0d3530957">
在方法中,添加一句:
http.csrf().disable();
问题解决。