Spring Cloud 之Spring-Security


對於Spring-Security首先要明白這么幾點:

1、什么是SpringSecurityurity
2、SpringSecurity應用場景
3、SpringBoot整合Security
4、Security formLogin 模式
5、Security httpBasic模式
6、Security 實現賬號權限控制
7、Security 自定義登陸界面
8、RBAC權限控制模型
http://pig.pigx.top/#/admin/role

 

什么是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=aladdin

SpringSecurity官網:https://spring.io/projects/spring-security
Spring整合SpringSecurityu
SpringBoot整合SpringSecurityu

 

微服務安全框架 SpringBootSecurity
Security應用場景

Security在很多企業中作為后台角色權限框架、授權認證oauth2.0 、安全防護(防止跨站點請求)、Session攻擊、非常容易融合SpringMVC使用等

有兩個賬戶
admin 賬戶 所有請求都有權限訪問
userAdd賬戶 只能訪問查詢和添加訂單權限
403 權限不足
401 沒有授權

 

環境搭建:

  admin賬戶  所有請求都有權限訪問

  userAdd賬戶  只能訪問查詢和添加訂單

  

  關於 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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM