|
| 1 | +# SpringBoot整合SpringSecurity |
| 2 | + |
| 3 | +支持作者就star一下✔ |
| 4 | + |
| 5 | +Spring Security是一个功能强大且可高度自定义的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。 |
| 6 | + |
| 7 | +Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正强大之处在于它可以轻松扩展以满足自定义要求。 |
| 8 | + |
| 9 | +**特征** |
| 10 | + |
| 11 | +- 对身份验证和授权的全面和可扩展的支持 |
| 12 | +- 防止会话固定,点击劫持,跨站点请求伪造等攻击 |
| 13 | +- Servlet API集成 |
| 14 | +- 可选与Spring Web MVC集成 |
| 15 | +- [更多可以参考官网](https://spring.io/projects/spring-security#learn) … |
| 16 | + |
| 17 | +# 依赖 |
| 18 | +spring security整合springboot所使用的依赖 |
| 19 | +```xml |
| 20 | + <dependency> |
| 21 | + <groupId>org.springframework.boot</groupId> |
| 22 | + <artifactId>spring-boot-starter-security</artifactId> |
| 23 | + </dependency> |
| 24 | +``` |
| 25 | +spring security标签依赖 |
| 26 | + |
| 27 | +```xml |
| 28 | + <dependency> |
| 29 | + <groupId>org.thymeleaf.extras</groupId> |
| 30 | + <artifactId>thymeleaf-extras-springsecurity5</artifactId> |
| 31 | + </dependency> |
| 32 | +``` |
| 33 | +Html页面上使用标签库 |
| 34 | +```html |
| 35 | +<html xmlns:th="http://www.thymeleaf.org" |
| 36 | + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> |
| 37 | +``` |
| 38 | +Jsp页面上使用标签库 |
| 39 | +```html |
| 40 | +< %@ taglib prefix ="sec" uri ="http://www.springframework.org/security/tags" % > |
| 41 | +``` |
| 42 | +标签使用简单案例:判断是否已经登录 |
| 43 | +```html |
| 44 | +<div sec:authorize="!isAuthenticated()"> |
| 45 | + <h4 align="center">游客您好,<a th:href="@{/login}">请登录</a></h4> |
| 46 | +</div> |
| 47 | +``` |
| 48 | +# 配置文件 |
| 49 | +SpringSecurity配置 |
| 50 | +```java |
| 51 | +@EnableWebSecurity |
| 52 | +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { |
| 53 | + |
| 54 | + /** |
| 55 | + * 认证请求规则 |
| 56 | + * |
| 57 | + * @param http |
| 58 | + * @throws Exception |
| 59 | + */ |
| 60 | + @Override |
| 61 | + protected void configure(HttpSecurity http) throws Exception { |
| 62 | + http.authorizeRequests().antMatchers("/").permitAll() |
| 63 | + .antMatchers("/level1/**").hasRole("VIP1") |
| 64 | + .antMatchers("/level2/**").hasRole("VIP2") |
| 65 | + .antMatchers("/level3/**").hasRole("VIP3"); |
| 66 | + // 注销账号 |
| 67 | + http.logout().logoutSuccessUrl("/"); |
| 68 | + /****************** 默认的 ****************/ |
| 69 | + // 默认登录表单 |
| 70 | + http.formLogin(); |
| 71 | + // 记住我 |
| 72 | + http.rememberMe(); |
| 73 | + |
| 74 | + /****************** 定制的 ****************/ |
| 75 | + // 定制页面和参数,默认名称:username,password |
| 76 | + // http.formLogin().loginPage("/login").usernameParameter("userName").passwordParameter("userPwd"); |
| 77 | + // 定制记住我 |
| 78 | + // http.rememberMe().rememberMeParameter("remember"); |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * 授权 |
| 83 | + * |
| 84 | + * @param auth |
| 85 | + * @throws Exception |
| 86 | + */ |
| 87 | + @Override |
| 88 | + protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
| 89 | + auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder()) |
| 90 | + .withUser("tellsea").password("123456").roles("VIP1", "VIP2") |
| 91 | + .and() |
| 92 | + .withUser("zhangsan").password("123456").roles("VIP2", "VIP3") |
| 93 | + .and() |
| 94 | + .withUser("lisi").password("123456").roles("VIP1", "VIP3"); |
| 95 | + } |
| 96 | +} |
| 97 | +``` |
| 98 | +密码验证器 |
| 99 | + |
| 100 | +> 解决报错:There is no PasswordEncoder mapped for the id “null” |
| 101 | +
|
| 102 | +```java |
| 103 | +public class MyPasswordEncoder implements PasswordEncoder { |
| 104 | + |
| 105 | + @Override |
| 106 | + public String encode(CharSequence charSequence) { |
| 107 | + return charSequence.toString(); |
| 108 | + } |
| 109 | + |
| 110 | + @Override |
| 111 | + public boolean matches(CharSequence charSequence, String s) { |
| 112 | + return s.equals(charSequence.toString()); |
| 113 | + } |
| 114 | +} |
| 115 | +``` |
| 116 | +报错的原因 |
| 117 | + |
| 118 | +因为Spring security 5.0中新增了多种加密方式,也改变了密码的格式。 |
| 119 | + |
| 120 | +Spring Security中密码的存储格式是“{id}…………”。前面的id是加密方式,id可以是bcrypt、sha256等,后面跟着的是加密后的密码。 |
| 121 | + |
| 122 | +也就是说,程序拿到传过来的密码的时候,会首先查找被“{”和“}”包括起来的id,来确定后面的密码是被怎么样加密的,如果找不到就认为id是null。这也就是为什么我们的程序会报错。 |
| 123 | + |
| 124 | +官方文档举的例子中是各种加密方式针对同一密码加密后的存储形式,原始密码都是“password”。 |
| 125 | + |
| 126 | +# 控制层测试 |
| 127 | +```java |
| 128 | +@Controller |
| 129 | +public class PageController { |
| 130 | + |
| 131 | + @GetMapping({"/", "", "/index"}) |
| 132 | + public String index() { |
| 133 | + return "index"; |
| 134 | + } |
| 135 | + |
| 136 | + // 定制的登录表单 |
| 137 | + @GetMapping("/login") |
| 138 | + public String login() { |
| 139 | + return "login"; |
| 140 | + } |
| 141 | + |
| 142 | + @GetMapping("level1") |
| 143 | + @ResponseBody |
| 144 | + public String level1() { |
| 145 | + return "level1 拥有角色VIP1"; |
| 146 | + } |
| 147 | + |
| 148 | + @GetMapping("level2") |
| 149 | + @ResponseBody |
| 150 | + public String level2() { |
| 151 | + return "level2 拥有角色VIP2"; |
| 152 | + } |
| 153 | + |
| 154 | + @GetMapping("level3") |
| 155 | + @ResponseBody |
| 156 | + public String level3() { |
| 157 | + return "level3 拥有角色VIP3"; |
| 158 | + } |
| 159 | +} |
| 160 | +``` |
| 161 | +# 测试页面 |
| 162 | +index.html |
| 163 | +```html |
| 164 | +<html xmlns:th="http://www.thymeleaf.org" |
| 165 | + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> |
| 166 | +<head> |
| 167 | + <meta charset="UTF-8"> |
| 168 | + <title>SpringBoot 整合 SpringSecurity</title> |
| 169 | +</head> |
| 170 | +<body> |
| 171 | +<h2 align="center">SpringBoot 整合 SpringSecurity 实现登录、授权案例</h2> |
| 172 | +<div sec:authorize="!isAuthenticated()"> |
| 173 | + <h4 align="center">游客您好,<a th:href="@{/login}">请登录</a></h4> |
| 174 | +</div> |
| 175 | +<div sec:authorize="isAuthenticated()"> |
| 176 | + <h4><span sec:authentication="name"></span>,您拥有的角色:<span sec:authentication="principal.authorities"></span></h4> |
| 177 | + <form th:action="@{/logout}" method="post"> |
| 178 | + <input type="submit" value="注销"/> |
| 179 | + </form> |
| 180 | +</div> |
| 181 | +<hr> |
| 182 | +<ul> |
| 183 | + <div sec:authorize="hasRole('VIP1')"> |
| 184 | + <li><a th:href="@{/level1}">VIP1,可以访问</a></li> |
| 185 | + </div> |
| 186 | + <div sec:authorize="hasRole('VIP2')"> |
| 187 | + <li><a th:href="@{/level2}">VIP2,可以访问</a></li> |
| 188 | + </div> |
| 189 | + <div sec:authorize="hasRole('VIP3')"> |
| 190 | + <li><a th:href="@{/level3}">VIP3,可以访问</a></li> |
| 191 | + </div> |
| 192 | +</ul> |
| 193 | +</body> |
| 194 | +</html> |
| 195 | +``` |
| 196 | +login.html |
| 197 | +```html |
| 198 | +<html xmlns:th="http://www.thymeleaf.org"> |
| 199 | +<head> |
| 200 | + <meta charset="UTF-8"> |
| 201 | + <title>定制的登录表单</title> |
| 202 | +</head> |
| 203 | +<body> |
| 204 | +<h2 align="center">定制登录页面</h2> |
| 205 | +<hr> |
| 206 | +<form th:action="@{/login}" method="post" style="margin: auto; width: 200px;"> |
| 207 | + 用户名:<input type="text" name="userName"><br> |
| 208 | + 密码:<input type="password" name="userPwd"><br> |
| 209 | + <input type="checkbox" name="remember"> 记住我<br> |
| 210 | + <input type="submit" value="登录"> |
| 211 | +</form> |
| 212 | +</body> |
| 213 | +</html> |
| 214 | +``` |
0 commit comments