對於Spring-Security首先要明白這麼幾點:css
一、什麼是SpringSecurityurity
二、SpringSecurity應用場景
三、SpringBoot整合Security
四、Security formLogin 模式
五、Security httpBasic模式
六、Security 實現帳號權限控制
七、Security 自定義登錄界面
八、RBAC權限控制模型
http://pig.pigx.top/#/admin/rolehtml
什麼是SpringSecurityu
Spring Security是一個可以爲基於Spring的企業應用系統提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組能夠在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,爲應用系統提供聲明式的安全訪問控制功能,減小了爲企業系統安全控制編寫大量重複代碼的工做。
參考百度百科:https://baike.baidu.com/item/spring%20security/8831652?fr=aladdinjava
SpringSecurity官網:https://spring.io/projects/spring-security
Spring整合SpringSecurityu
SpringBoot整合SpringSecurityuweb
微服務安全框架 SpringBootSecurity
Security應用場景spring
Security在不少企業中做爲後臺角色權限框架、受權認證oauth2.0 、安全防禦(防止跨站點請求)、Session攻擊、很是容易融合SpringMVC使用等數據庫
有兩個帳戶
admin 帳戶 全部請求都有權限訪問
userAdd帳戶 只能訪問查詢和添加訂單權限
403 權限不足
401 沒有受權編程
環境搭建:瀏覽器
admin帳戶 全部請求都有權限訪問緩存
userAdd帳戶 只能訪問查詢和添加訂單tomcat
關於 formLogin模式 : 表單提交認證模式
httpBasic模式 :瀏覽器與服務器作認證受權
maven的依賴主要:
<!-->spring-boot 整合security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
關於HttpBasic模式:
在HTTP協議進行通訊的過程當中,HTTP協議定義了基本認證過程以容許HTTP服務器對WEB瀏覽器進行用戶身份證的方法,當一個客戶端向HTTP服務 器進行數據請求時,若是客戶端未被認證,則HTTP服務器將經過基本認證過程對客戶端的用戶名及密碼進行驗證,以決定用戶是否合法。客戶端在接收到HTTP服務器的身份認證要求後,會提示用戶輸入用戶名及密碼,而後將用戶名及密碼以BASE64加密,加密後的密文將附加於請求信息中, 如當用戶名爲toov5,密碼爲:123456時,客戶端將用戶名和密碼用「:」合併,並將合併後的字符串用BASE64加密爲密文,並於每次請求數據 時,將密文附加於請求頭(Request Header)中。HTTP服務器在每次收到請求包後,根據協議取得客戶端附加的用戶信息(BASE64加密的用戶名和密碼),解開請求包,對用戶名及密碼進行驗證,若是用 戶名及密碼正確,則根據客戶端請求,返回客戶端所須要的數據;不然,返回錯誤代碼或從新要求客戶端提供用戶名及密碼。
maven:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依賴 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- SpringBoot整合Web組件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- springboot整合freemarker --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!-->spring-boot 整合security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> <!-- 注意: 這裏必需要添加, 否者各類依賴有問題 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
Controller:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class OrderController { // 首頁 @RequestMapping("/") public String index() { return "index"; } // 查詢訂單 @RequestMapping("/showOrder") public String showOrder() { return "showOrder"; } // 添加訂單 @RequestMapping("/addOrder") public String addOrder() { return "addOrder"; } // 修改訂單 @RequestMapping("/updateOrder") public String updateOrder() { return "updateOrder"; } // 刪除訂單 @RequestMapping("/deleteOrder") public String deleteOrder() { return "deleteOrder"; } // 自定義登錄頁面 @GetMapping("/login") public String login() { return "login"; } }
對於403狀態碼的錯誤處理:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ErrorController { // 403權限不足頁面 @RequestMapping("/error/403") public String error() { return "/error/403"; } }
config:
權限的配置:
對於fromLogin登陸頁面的修改自定義 關閉csdrf 配置loginpage就OK了
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; 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; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.stereotype.Component; import com.mayikt.handler.MyAuthenticationFailureHandler; import com.mayikt.handler.MyAuthenticationSuccessHandler; // Security 配置 @Component @EnableWebSecurity //繼承這個類 public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyAuthenticationFailureHandler failureHandler; @Autowired private MyAuthenticationSuccessHandler successHandler; // 配置認證用戶信息和權限 protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 添加admin帳號 auth.inMemoryAuthentication().withUser("admin").password("123456"). authorities("showOrder","addOrder","updateOrder","deleteOrder"); // 添加userAdd帳號 auth.inMemoryAuthentication().withUser("userAdd").password("123456").authorities("showOrder","addOrder"); // 若是想實現動態帳號與數據庫關聯 在該地方改成查詢數據庫 } // 配置攔截請求資源 protected void configure(HttpSecurity http) throws Exception { // 如何權限控制 給每個請求路徑 分配一個權限名稱 讓後帳號只要關聯該名稱,就能夠有訪問權限 http.authorizeRequests() // 配置查詢訂單權限 .antMatchers("/showOrder").hasAnyAuthority("showOrder") .antMatchers("/addOrder").hasAnyAuthority("addOrder") .antMatchers("/login").permitAll() //登陸請求不能夠攔截! .antMatchers("/updateOrder").hasAnyAuthority("updateOrder") .antMatchers("/deleteOrder").hasAnyAuthority("deleteOrder") .antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login"). //配置登陸頁面!! successHandler(successHandler).failureHandler(failureHandler) //成功和失敗的配置 .and().csrf().disable(); //csrf跨站點攻擊關閉 不然必需要傳遞token!! } @Bean public static NoOpPasswordEncoder passwordEncoder() { return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); } }
權限相關頁面配置:自定義web服務器參數
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; @Configuration public class WebServerAutoConfiguration { @Bean public ConfigurableServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400"); ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401"); ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403"); ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"); ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415"); ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"); factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500); return factory; } }
AuthenticationFailureHandler 認證失敗接口
AuthenticationSuccessHandler 認證成功接口
成功和失敗的處理:
失敗:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; //認證失敗 @Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res, AuthenticationException auth) throws IOException, ServletException { System.out.println("登錄失敗!"); res.sendRedirect("http://baidu.com"); } }
成功:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; // 認證成功 @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication arg2) throws IOException, ServletException { System.out.println("用戶認證成功"); res.sendRedirect("/"); } }
啓動類:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AppSecurity { public static void main(String[] args) { SpringApplication.run(AppSecurity.class, args); // Security 兩種模式 fromLogin 表單提交認證模式 httpBasic 瀏覽器與服務器作認證受權 } }
yml:
# 配置freemarker
spring:
freemarker:
# 設置模板後綴名
suffix: .ftl
# 設置文檔類型
content-type: text/html
# 設置頁面編碼格式
charset: UTF-8
# 設置頁面緩存
cache: false
# 設置ftl文件路徑
template-loader-path:
- classpath:/templates
# 設置靜態文件路徑,js,css等
mvc:
static-path-pattern: /static/**
頁面:
login.ftl:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <h1>Toov5--權限控制登錄系統</h1> <form action="/login" method="post"> <span>用戶名稱</span><input type="text" name="username" /> <br> <span>用戶密碼</span><input type="password" name="password" /> <br> <input type="submit" value="登錄"> </form> <#if RequestParameters['error']??> 用戶名稱或者密碼錯誤 </#if> </body> </html>