SpringBoot高级_与安全

编程入门 行业动态 更新时间:2024-10-27 06:34:34

SpringBoot<a href=https://www.elefans.com/category/jswz/34/1770104.html style=高级_与安全"/>

SpringBoot高级_与安全

一、创建测试工程
 1、引入依赖:这时还没有引入spring-security

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

2、编写前端页面:

level1/1.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>罗汉拳</h1>
<p>罗汉拳站当央,打起来不要慌</p>
</body>
</html>

level1/2.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>武当长拳</h1>
<p>长一点在长一点</p>
</body>
</html>

level1/3.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>全真剑法</h1>
<p>全都是真的</p>
</body>
</html>

level2/1.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>太极拳</h1>
<p>一个西瓜圆又圆 劈它一刀成两半 你一半来 给你你不要 给他他不收 那就不给 把两人撵走 他们不走你走 走啦,一挥手,伤自尊不买西瓜别缠我,缓慢纠缠様 两人缠我赖皮,手慢动作左右挥动 看我厉害,转头缓步拍苍蝇状 拍死了,手抱西瓜状+奥特曼十字手+广播操准备运动的站立
</p>
</body>
</html>

level2/2.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>七伤拳</h1>
<p>练这拳的人全都死了</p>
</body>
</html>

level2/3.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>梯云纵</h1>
<p>踩自己的脚往上跳</p>
</body>
</html>

level3/1.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>葵花宝典</h1>
<p>欲练神功,挥刀自宫</p>
</body>
</html>

level3/2.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>龟派气功</h1>
<p>龟-派-气-功-波</p>
</body>
</html>

level3/3.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<a th:href="@{/}">返回</a>
<h1>独孤九剑</h1>
<p>欲练此剑,必先犯贱</p>
</body>
</html>

login.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta charset="UTF-8"><title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎登陆武林秘籍管理系统</h1>
<hr>
<div align="center"><form action="" method="post">用户名:<input name=""/><br>密码:<input name=""><br/><input type="submit" value="登陆"></form>
</div>
</body>
</html>

welcome.html:

<!DOCTYPE html>
<html xmlns:th="">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎光临武林秘籍管理系统</h1>
<h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/login}">请登录</a></h2>
<hr><h3>普通武功秘籍</h3>
<ul><li><a th:href="@{/level1/1}">罗汉拳</a></li><li><a th:href="@{/level1/2}">武当长拳</a></li><li><a th:href="@{/level1/3}">全真剑法</a></li>
</ul><h3>高级武功秘籍</h3>
<ul><li><a th:href="@{/level2/1}">太极拳</a></li><li><a th:href="@{/level2/2}">七伤拳</a></li><li><a th:href="@{/level2/3}">梯云纵</a></li>
</ul><h3>绝世武功秘籍</h3>
<ul><li><a th:href="@{/level3/1}">葵花宝典</a></li><li><a th:href="@{/level3/2}">龟派气功</a></li><li><a th:href="@{/level3/3}">独孤九剑</a></li>
</ul></body>
</html>

3、编写访问页面的controller:此时访问/时会路由到welcome.html

@Controller
public class KungfuController {private final String PREFIX = "pages/";/*** 欢迎页** @return*/@GetMapping("/")public String index() {return "welcome";}/*** 登陆页** @return*/@GetMapping("/userlogin")public String loginPage() {return PREFIX + "login";}/*** level1页面映射** @param path* @return*/@GetMapping("/level1/{path}")public String level1(@PathVariable("path") String path) {return PREFIX + "level1/" + path;}/*** level2页面映射** @param path* @return*/@GetMapping("/level2/{path}")public String level2(@PathVariable("path") String path) {return PREFIX + "level2/" + path;}/*** level3页面映射** @param path* @return*/@GetMapping("/level3/{path}")public String level3(@PathVariable("path") String path) {return PREFIX + "level3/" + path;}
}

4、启动测试:http://localhost:8080/


  若SpringBoot版本太低,在访问时可能会因为引入的thymeleaf版本太低(不支持html的一些新标签)而报错,此时可在pom中更改SpringBoot默认引用的thymeleaf的版本:在properties节点中更改

<properties><thymeleaf.version>3.0.9.RELEASE</thymeleaf.version><thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
</properties>

二、认证和授权
  安全框架的两个主要职能是“认证”和“授权”(或者访问控制),这两个主要职能也是Spring Security 的两个目标。
  认证(Authentication):辨明主体是谁,是建立一个安全主体的过程(主体一般是指用户、设备或一些可以在你的应用程序中执行动作的其他系统)
  授权(Authorization):主体在系统中能干什么,确定一个主体是否允许在你的应用程序执行一个动作(比如查看某个页面资源)的过程。授权之前主体的身份已经有认证,即授权是在认证之后决定主体拥有哪些权限

三、使用Spring Security
 1、引入spring security

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、参照官网编写一个spring security的配置类:示例地址
  示例:配置类继承于WebSecurityConfigurerAdapter,并须添加@EnableWebSecurity注解

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/css/**", "/index").permitAll()		.antMatchers("/user/**").hasRole("USER")			.and().formLogin().loginPage("/login").failureUrl("/login-error");	}@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");}
}

自定义SecurityConfig :定制授权规则

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//定制授权规则http.authorizeRequests().antMatchers("/").permitAll()//所有用户可访问"/",即主页.antMatchers("/level1/**").hasRole("VIP1")//访问URL中含有/level1的资源需有VIP1权限.antMatchers("/level2/**").hasRole("VIP2")//访问URL中含有/level2的资源需有VIP2权限.antMatchers("/level3/**").hasRole("VIP3");//访问URL中含有/level3的资源需有VIP3权限}
}

此时再访问未授权的资源时会被拒绝

开启登录功能:调用HttpSecurity的formLogin()

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll()//所有用户可访问"/",即主页.antMatchers("/level1/**").hasRole("VIP1")//访问URL中含有/level1的资源需有VIP1权限.antMatchers("/level2/**").hasRole("VIP2")//访问URL中含有/level2的资源需有VIP2权限.antMatchers("/level3/**").hasRole("VIP3");//访问URL中含有/level3的资源需有VIP3权限//开启自动配置的登录功能http.formLogin();}
}

在访问未经授权的资源时会发送/login请求跳转到Security提供的登录页面,如果填写的登录信息有误会发送(login?error)请求跳转到Security提供的登录错误页面,我们也可以设置登录的用户名密码等字段名的信息
   登录页:


   登录失败:


 3、认证:以上为Security的授权,接下来是Security的认证:

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {/*** 授权** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll()//所有用户可访问"/",即主页.antMatchers("/level1/**").hasRole("VIP1")//访问URL中含有/level1的资源需有VIP1权限.antMatchers("/level2/**").hasRole("VIP2")//访问URL中含有/level2的资源需有VIP2权限.antMatchers("/level3/**").hasRole("VIP3");//访问URL中含有/level3的资源需有VIP3权限//开启自动配置的登录功能http.formLogin();}/*** 开启认证功能** @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication()//在内存的数据中认证.withUser("zhangsan").password("123456").roles("VIP1", "VIP2")//配置用户名、密码和角色信息.and().withUser("lisi").password("654321").roles("VIP3");}
}

在高版本的Spring Security中使用以上的认证方式可能会报错:

There is no PasswordEncoder mapped for the id "null"

这是因为高版本中需要指定密码的加密方式,代码如下:

/*** 开启认证功能** @param auth* @throws Exception*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication()//在内存的数据中认证.passwordEncoder(new BCryptPasswordEncoder())//指定密码的编码方式.withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP1", "VIP2")//配置用户名、密码和角色信息.and().withUser("lisi").password(new BCryptPasswordEncoder().encode("654321")).roles("VIP3");//使用Bcrypt对密码进行加密
}

4、注销:调用HttpSecurity.logout()开启注销功能,前端访问/logout请求即可

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {/*** 授权** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll()//所有用户可访问"/",即主页.antMatchers("/level1/**").hasRole("VIP1")//访问URL中含有/level1的资源需有VIP1权限.antMatchers("/level2/**").hasRole("VIP2")//访问URL中含有/level2的资源需有VIP2权限.antMatchers("/level3/**").hasRole("VIP3");//访问URL中含有/level3的资源需有VIP3权限//开启自动配置的登录功能http.formLogin();//开启自动配置的注销功能http.logout();}
}

前端请求:请求地址/logout,请求方式必须是post

<form th:action="@{/logout}" method="post"><input type="submit" value="注销"/>
</form>

开启自动配置的注销功能后只需要访问/logout请求即可清空session(Spring Security已为我们提供了/logout请求的处理,无需我们编写处理逻辑,应该也可以自定义处理逻辑);注销成功后默认会重定向到登录页(访问/login?logout),我们可以定制重定向的路径:设置logoutSuccessUrl的值即可

http.logout().logoutSuccessUrl("/");

四、页面根据授权展示内容
 1、引入Spring Security整合thymeleaf的依赖:注意版本要和Spring Security对应

<dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity5</artifactId><version>3.0.4.RELEASE</version><!-- 该版本可以不指定 -->
</dependency>

由于SpringBoot默认指定了Spring Security和thymeleaf以及他们整合时的版本

<spring-security.version>5.1.3.RELEASE</spring-security.version>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<thymeleaf-extras-springsecurity.version>3.0.4.RELEASE</thymeleaf-extras-springsecurity.version>

但是该版本可能和thymeleaf-extras-springsecurity5不匹配,这时我们可以在pom文件中修改版本:若匹配则无需修改

<properties><thymeleaf-extras-springsecurity4.version>3.0.2.RELEASE</thymeleaf-extras-springsecurity.version>
</properties>

2、在页面上引入Security的名称空间

<html xmlns:sec="">

在页面上使用引入的名称空间:
  ①未登录则显示登录按钮,否则不显示:sec:authorize="!isAuthenticated()"

<div sec:authorize="!isAuthenticated()"><h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
</div>

②登录成功显示注销按钮,并显示当前登录者和授予权限:sec:authentication="name"获取登录者,sec:authentication="principal.authorities"获取授予权限

<div sec:authorize="isAuthenticated()"><h2><span sec:authentication="name"></span>,您好,您的角色有:<span sec:authentication="principal.authorities"></span></h2><form th:action="@{/logout}" method="post"><input type="submit" value="注销"/></form>
</div>

③根据登录者拥有的角色显示对应的武功秘籍:sec:authorize=“hasRole(‘VIP3’)”

<div sec:authorize="hasRole('VIP3')"><h3>绝世武功秘籍</h3><ul><li><a th:href="@{/level3/1}">葵花宝典</a></li><li><a th:href="@{/level3/2}">龟派气功</a></li><li><a th:href="@{/level3/3}">独孤九剑</a></li></ul>
</div>

五、记住我
 1、开启记住我功能:调用HttpSecurity的rememberMe()

protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll()//所有用户可访问"/",即主页.antMatchers("/level1/**").hasRole("VIP1")//访问URL中含有/level1的资源需有VIP1权限.antMatchers("/level2/**").hasRole("VIP2")//访问URL中含有/level2的资源需有VIP2权限.antMatchers("/level3/**").hasRole("VIP3");//访问URL中含有/level3的资源需有VIP3权限//开启自动配置的登录功能http.formLogin();//开启自动配置的注销功能http.logout().logoutSuccessUrl("/");//开启记住我功能http.rememberMe();
}


 原理:开启Spring Security的记住我功能之后,一旦我们勾选了记住我,Spring Security就会给浏览器发送一个默认名为remember-me的cookie,默认的有效期限为14天,这样我们14天内(14天后该cookie会自动删除)使用该浏览器再次访问该网址的时候浏览器就会携带着这个cookie,Spring Security就会根据该cookie查找cookie的有效性以及登录人员的信息等,我们点击注销后,Spring Security会删除浏览器端的cookie

 注销:

更多推荐

SpringBoot高级_与安全

本文发布于:2023-07-28 19:19:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1285460.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:高级   SpringBoot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!