-
在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。
-
在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。
-
使用过滤器、拦截器也可以使用
Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。
“认证”(Authentication)
身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。
身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。
“授权” (Authorization)
授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。
这个概念是通用的,而不是只在Spring Security 中存在。
实现过程
15.4 实现
1、引入 Spring Security 依赖
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.10.1</version>
</dependency>
<!-- thymeleaf-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
2、编写 Spring Security 配置类SecurityConfig
-
参考官网:Spring Security
package com.studyspringboot.study.config.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//首页所有人可以访问
http.authorizeRequests(authorize -> authorize
.antMatchers("/index").permitAll()
.antMatchers("/").anonymous()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3"))
//没有权限跳转登录页
.formLogin(login -> login
.permitAll()
.loginPage("/toLogin")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/user/login")// 登陆表单提交请求
)
.logout(l -> l.logoutSuccessUrl("/index").deleteCookies())// 注销成功来到首页
.csrf(AbstractHttpConfigurer::disable)//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
.rememberMe(r -> r.rememberMeParameter("remember"))记住我 Cookies
;
return http.build();
}
//定义认证规则
@Bean
public UserDetailsService users() {
User.UserBuilder users = User.builder();
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
//{noop}明文密码
UserDetails w1 = User.withUsername("wyh").password("{noop}123456").roles("vip1").build();
UserDetails admin =
users.username("admin").password(encoder.encode("123456")).roles("vip1", "vip2", "vip3").build();
return new InMemoryUserDetailsManager(w1, admin);
}
}
3、配置前端权限
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<div class="bodyBox">
<!--如果已登录-->
<p sec:authorize="isAuthenticated()"><a th:href="@{/logout}" class="label label-warning"
style="border-radius: .25em;">注销</a></p>
<!--如果未登录-->
<p sec:authorize="!isAuthenticated()"><a th:href="@{/toLogin}" class="label label-success"
style="border-radius: .25em;">登录</a></p>
用户名:<span sec:authentication="principal.username"></span>
角色:<span sec:authentication="principal.authorities"></span>
<!--根据role权限过滤-->
<div class="cardBox" sec:authorize="isAuthenticated() and hasRole('vip1')">
<div class="bodyBox">
<p><a th:href="@{/level1/1}" class="label label-info" style="border-radius: .25em;">level1-1</a></p>
<p><a th:href="@{/level1/2}" class="label label-info" style="border-radius: .25em;">level1-2</a></p>
<p><a th:href="@{/level1/3}" class="label label-info" style="border-radius: .25em;">level1-3</a></p>
</div>
</div>
</div>