1. 程式人生 > >Spring Security技術棧開發企業級認證與授權(九)開發圖形驗證碼介面

Spring Security技術棧開發企業級認證與授權(九)開發圖形驗證碼介面

在設計登入模組的時候,圖形驗證碼基本上都是標配,本篇部落格重點介紹開發可重用的圖形驗證碼介面,該介面支援使用者自定義配置,比如驗證碼的長度、驗證碼圖形的寬度和高度等資訊。

本文的目標是開發一個圖形驗證碼介面,該驗證碼支援使用者自定義長度,以及生成圖片後圖片的寬度和高度、驗證碼的過期時間等。接下來按照整個設計思路介紹開發流程。

一、開發圖形驗證碼實體類及屬性類

1)圖形驗證碼實體類

圖形驗證碼一般都需要一個實體類來進行承載,在這裡我設定了三個屬性,分別是BufferedImage型別的屬性、String型別的驗證碼以及LocalDateTime型別的時間引數。具體的程式碼如下:

package com.lemon.security.core.validate.code;

import lombok.Data;

import java.awt.image.BufferedImage;
import java.time.LocalDateTime;

/**
 * 圖片驗證碼
 *
 * @author lemon
 * @date 2018/4/6 下午4:34
 */
@Data
public class ImageCode {

    private BufferedImage image;

    private String code;

    private
LocalDateTime expireTime; public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) { this.image = image; this.code = code; this.expireTime = expireTime; } public ImageCode(BufferedImage image, String code, int expireIn) { this.image = image; this
.code = code; this.expireTime = LocalDateTime.now().plusSeconds(expireIn); } public boolean isExpired() { return LocalDateTime.now().isAfter(expireTime); } }

這裡設定了兩個有參構造方法,常用的第二個有參構造方法的最後一個引數指定了驗證碼的過期時間,也就是在多少秒後失效。具體的判斷方法由LocalDateTime.now().isAfter(expireTime)來進行判斷的。

2)圖形驗證碼屬性類

圖形驗證碼的實體類是承載驗證碼的具體資訊,而屬性類是為了定義圖形驗證碼的長度、圖片的寬度高度以及驗證碼的過期時間等基本屬性。這些屬性支援使用者在YAML配置檔案中進行配置的,當然也具備了預設值。具體程式碼如下:

package com.lemon.security.core.properties;

import lombok.Data;

/**
 * 圖形驗證碼的預設配置
 *
 * @author lemon
 * @date 2018/4/6 下午9:42
 */
@Data
public class ImageCodeProperties {

    /**
     * 驗證碼寬度
     */
    private int width = 67;
    /**
     * 驗證碼高度
     */
    private int height = 23;
    /**
     * 驗證碼長度
     */
    private int length = 4;
    /**
     * 驗證碼過期時間
     */
    private int expireIn = 60;

    /**
     * 需要驗證碼的url字串,用英文逗號隔開
     */
    private String url;

}

為了保持和之前的瀏覽器的基本設定保持一致,這裡包裝一層配置,程式碼如下:

package com.lemon.security.core.properties;

import lombok.Data;

/**
 * 封裝多個配置的類
 *
 * @author lemon
 * @date 2018/4/6 下午9:45
 */
@Data
public class ValidateCodeProperties {

    private ImageCodeProperties image = new ImageCodeProperties();
}

再將這個類包裝到SecurityProperties類中,程式碼如下:

package com.lemon.security.core.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author lemon
 * @date 2018/4/5 下午3:08
 */
@Data
@ConfigurationProperties(prefix = "com.lemon.security")
public class SecurityProperties {

    private BrowserProperties browser = new BrowserProperties();

    private ValidateCodeProperties code = new ValidateCodeProperties();
}

那麼在配置檔案中配置的方法如下:

# 配置圖形驗證碼
com:
  lemon:
    security:
      code:
        image:
          length: 6
          url: /user,/user/*

這個配置相當於使用者自定義了驗證碼的長度為6,以及需要驗證碼的URI/user/uset/*,在預設的情況下,長度為4。這幾個類基本完成了圖形驗證碼的自定義功能。

二、編寫圖形驗證碼生成介面和實現類

圖形驗證碼其實是完全不需要編寫介面的,這裡編寫介面是為了方便使用者可以自定義介面的實現類,這樣就可以自己寫生成驗證碼的邏輯,而不是使用系統預設的生成方式。具體的介面如下:

package com.lemon.security.core.validate.code;

import org.springframework.web.context.request.ServletWebRequest;

/**
 * @author lemon
 * @date 2018/4/7 上午11:06
 */
public interface ValidateCodeGenerator {

    /**
     * 生成圖片驗證碼
     *
     * @param request 請求
     * @return ImageCode例項物件
     */
    ImageCode generate(ServletWebRequest request);
}

這裡為什麼會傳入一個ServletWebRequest型別的引數,是因為這個有許多對請求中引數操作的方法,十分方便,請看後面的實現類:

package com.lemon.security.core.validate.code;

import com.lemon.security.core.properties.SecurityProperties;
import lombok.Data;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @author lemon
 * @date 2018/4/7 上午11:09
 */
@Data
public class ImageCodeGenerator implements ValidateCodeGenerator {

    private static final String IMAGE_WIDTH_NAME = "width";
    private static final String IMAGE_HEIGHT_NAME = "height";
    private static final Integer MAX_COLOR_VALUE = 255;

    private SecurityProperties securityProperties;

    @Override
    public ImageCode generate(ServletWebRequest request) {
        int width = ServletRequestUtils.getIntParameter(request.getRequest(), IMAGE_WIDTH_NAME, securityProperties.getCode().getImage().getWidth());
        int height = ServletRequestUtils.getIntParameter(request.getRequest(), IMAGE_HEIGHT_NAME, securityProperties.getCode().getImage().getHeight());
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();

        Random random = new Random();

        // 生成畫布
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman", Font.ITALIC, 20));
        g.setColor(getRandColor(160, 200));
        for (int i = 0; i < 155; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 生成數字驗證碼
        StringBuilder sRand = new StringBuilder();
        for (int i = 0; i < securityProperties.getCode().getImage().getLength(); i++) {
            String rand = String.valueOf(random.nextInt(10));
            sRand.append(rand);
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(rand, 13 * i + 6, 16);
        }

        g.dispose();

        return new ImageCode(image, sRand.toString(), securityProperties.getCode().getImage().getExpireIn());
    }

    /**
     * 生成隨機背景條紋
     *
     * @param fc 前景色
     * @param bc 背景色
     * @return RGB顏色
     */
    private Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > MAX_COLOR_VALUE) {
            fc = MAX_COLOR_VALUE;
        }
        if (bc > MAX_COLOR_VALUE) {
            bc = MAX_COLOR_VALUE;
        }
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }
}

這裡提供了生成圖片驗證碼的具體實現,其中兩行程式碼:

int width = ServletRequestUtils.getIntParameter(request.getRequest(), IMAGE_WIDTH_NAME, securityProperties.getCode().getImage().getWidth());
int height = ServletRequestUtils.getIntParameter(request.getRequest(), IMAGE_HEIGHT_NAME, securityProperties.getCode().getImage().getHeight());

這個是由Spring提供的工具類來獲取請求中的引數,第一個引數是HttpServletRequest請求,第二個是引數名字,第三個是預設值,如果沒有獲取到指定名稱的引數的值,那麼就使用這個預設值。從這兩行程式碼中可知,請求引數的寬度和高度的優先順序將大於YAML配置檔案中的引數,更加大於預設引數。本來這個類是可以使用@Component註解來標記為SpringBean的,但是沒有這麼做,這是因為這個實現類是本專案預設的,不一定完全符合使用者的需求,所以可以將其進行配置,而不是一定成為SpringBean。具體的配置如下程式碼:

package com.lemon.security.core.validate.code;

import com.lemon.security.core.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author lemon
 * @date 2018/4/7 上午11:22
 */
@Configuration
public class ValidateCodeBeanConfig {

    private final SecurityProperties securityProperties;

    @Autowired
    public ValidateCodeBeanConfig(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    @Bean
    @ConditionalOnMissingBean(name = "imageCodeGenerator")
    public ValidateCodeGenerator imageCodeGenerator() {
        ImageCodeGenerator imageCodeGenerator = new ImageCodeGenerator();
        imageCodeGenerator.setSecurityProperties(securityProperties);
        return imageCodeGenerator;
    }
}

其實這個配置和在ImageCodeGenerator類上使用@Component註解效果是一致的,都會被標記為SpringBean,但是在這裡,在配置的過程中使用了一個條件:@ConditionalOnMissingBean(name = "imageCodeGenerator"),也就是說上下文環境中如果沒有名稱為imageCodeGeneratorSpring Bean的話,那麼就配置專案預設的Bean,否則將不配置這個Bean,這也就是說,如果使用者自定義了一個類實現了ValidateCodeGenerator介面,並且實現類的在Spring容器中Bean的名字為imageCodeGenerator,那麼將使用使用者的實現類來生成圖形驗證碼。到現在這一步,基本完成了圖形驗證碼的核心需求。

三、編寫圖形驗證碼生成介面

圖形驗證碼介面將生成一個JPEG的圖片,那麼在前端就可以寫一個img標籤,src屬性指向介面。具體的Controller方法如下所示:

package com.lemon.security.core.validate.code;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author lemon
 * @date 2018/4/6 下午4:41
 */
@RestController
public class ValidateCodeController {

    static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";
    private static final String FORMAT_NAME = "JPEG";

    private final ValidateCodeGenerator imageCodeGenerator;

    private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();

    @Autowired
    public ValidateCodeController(ValidateCodeGenerator imageCodeGenerator) {
        this.imageCodeGenerator = imageCodeGenerator;
    }

    @GetMapping("/code/image")
    public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 第一步:根據請求生成一個圖形驗證碼物件
        ImageCode imageCode = imageCodeGenerator.generate(new ServletWebRequest(request));
        // 第二步:將圖形驗證碼物件存到session中,第一個引數可以從傳入的請求中獲取session
        sessionStrategy.setAttribute(new ServletRequestAttributes(request), SESSION_KEY, imageCode);
        // 第三步:將生成的圖片寫到介面的響應中
        ImageIO.write(imageCode.getImage(), FORMAT_NAME, response.getOutputStream());
    }
}

這裡使用imageCodeGenerator物件的generate方法生成了圖形驗證碼,並將驗證碼存入到了session中,最後將圖片寫回到輸出流中。

四、編寫驗證碼的校驗邏輯

驗證碼生成以後自動寫回到了瀏覽器頁面上,並以圖片的形式進行了展示,與此同時,生成的圖形驗證碼被設定了過期時間,並存入到session中,當用戶登入的時候,正確的邏輯是將登入的驗證碼引數取出來和session中的驗證碼進行對比,如果驗證碼對比通過後才開始驗證使用者名稱和密碼,由於使用者名稱和密碼的驗證用的是UsernamePasswordAuthenticationFilter來進行驗證的,所以這裡也需要寫一個過濾器,並且將這個過濾器放在UsernamePasswordAuthenticationFilter之前。先來編寫過濾器:

package com.lemon.security.core.validate.code;

import com.lemon.security.core.properties.SecurityProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author lemon
 * @date 2018/4/6 下午8:23
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private static final String SUBMIT_FORM_DATA_PATH = "/authentication/form";

    private AuthenticationFailureHandler authenticationFailureHandler;

    private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();

    private Set<String> urls = new HashSet<>();

    private SecurityProperties securityProperties;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        String[] configUrls = StringUtils.splitByWholeSeparatorPreserveAllTokens(securityProperties.getCode().getImage().getUrl(), ",");
        urls.addAll(Arrays.asList(configUrls));
        // 登入的連結是必須要進行驗證碼驗證的
        urls.add(SUBMIT_FORM_DATA_PATH);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        boolean action = false;
        for (String url : urls) {
            // 如果實際訪問的URL可以與使用者在YML配置檔案中配置的相同,那麼就進行驗證碼校驗
            if (antPathMatcher.match(url, request.getRequestURI())) {
                action = true;
            }
        }
        if (action) {
            try {
                validate(new ServletWebRequest(request));
            } catch (ValidateCodeException e) {
                authenticationFailureHandler.onAuthenticationFailure(request, response, e);
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 驗證碼校驗邏輯
     *
     * @param request 請求
     * @throws ServletRequestBindingException 請求異常
     */
    private void validate(ServletWebRequest request) throws ServletRequestBindingException {
        // 從session中獲取圖片驗證碼
        ImageCode imageCodeInSession = (ImageCode) sessionStrategy.getAttribute(request, ValidateCodeController.SESSION_KEY);
        // 從請求中獲取使用者填寫的驗證碼
        String imageCodeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "imageCode");
        if (StringUtils.isBlank(imageCodeInRequest)) {
            throw new ValidateCodeException("驗證碼不能為空");
        }
        if (null == imageCodeInSession) {
            throw new ValidateCodeException("驗證碼不存在");
        }
        if (imageCodeInSession.isExpired()) {
            sessionStrategy.removeAttribute(request, ValidateCodeController.SESSION_KEY);
            throw new ValidateCodeException("驗證碼已過期");
        }
        if (!StringUtils.equalsIgnoreCase(imageCodeInRequest, imageCodeInSession.getCode())) {
            throw new ValidateCodeException("驗證碼不匹配");
        }
        // 驗證成功,刪除session中的驗證碼
        sessionStrategy.removeAttribute(request, ValidateCodeController.SESSION_KEY);
    }
}

這個過濾器繼承了OncePerRequestFilter,這就保證了一次請求僅僅會執行一次過濾器,不會重複執行。而實現InitializingBean是為了當前類作為Spring Bean進行例項化完成(成員屬性全部初始化完成)的時候,會自動呼叫這個介面的afterPropertiesSet方法,當然,如果這個類沒有被Spring進行例項化,那麼就需要手動呼叫這個方法,這裡就是使用的手動呼叫afterPropertiesSet方法。這裡afterPropertiesSet方法是將使用者配置的需要對驗證碼進行校驗的連線進行裝配,將以英文逗號隔開的連線裝配到字串陣列中。在後面的doFilterInternal方法中,將遍歷這個字串陣列,如果當前訪問的連結包含在這個陣列中,將進行校驗操作,否則該過濾器直接放行。具體的校驗邏輯請看上面的程式碼,很簡單。前面已經說了,需要將該過濾器加入到UsernamePasswordAuthenticationFilter之前,具體的做法就是使用addFilterBefore方法,具體的程式碼如下:

package com.lemon.security.browser;

import com.lemon.security.core.properties.SecurityProperties;
import com.lemon.security.core.validate.code.ValidateCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * 瀏覽器安全驗證的配置類
 *
 * @author lemon
 * @date 2018/4/3 下午7:35
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    private final SecurityProperties securityProperties;
    private final AuthenticationSuccessHandler lemonAuthenticationSuccessHandler;
    private final AuthenticationFailureHandler lemonAuthenticationFailureHandler;

    @Autowired
    public BrowserSecurityConfig(SecurityProperties securityProperties, AuthenticationSuccessHandler lemonAuthenticationSuccessHandler, AuthenticationFailureHandler lemonAuthenticationFailureHandler) {
        this.securityProperties = securityProperties;
        this.lemonAuthenticationSuccessHandler = lemonAuthenticationSuccessHandler;
        this.lemonAuthenticationFailureHandler = lemonAuthenticationFailureHandler;
    }

    /**
     * 配置了這個Bean以後,從前端傳遞過來的密碼將被加密
     *
     * @return PasswordEncoder實現類物件
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
        validateCodeFilter.setAuthenticationFailureHandler(lemonAuthenticationFailureHandler);
        validateCodeFilter.setSecurityProperties(securityProperties);
        validateCodeFilter.afterPropertiesSet();

        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage("/authentication/require")
                .loginProcessingUrl("/authentication/form")
                .successHandler(lemonAuthenticationSuccessHandler)
                .failureHandler(lemonAuthenticationFailureHandler)
                .and()
                .authorizeRequests()
                .antMatchers("/authentication/require", securityProperties.getBrowser().getLoginPage(), "/code/image").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }
}

這就完成了全部的需求和功能,這時候啟動專案,訪問登陸介面,就可以看到如下圖片所示的情景:
這裡寫圖片描述
對於簡單的需求,生成驗證碼的邏輯很簡單,直接使用一個Controller即可,但是這裡為什麼使用繞這麼多的邏輯,這是因為這樣設計有框架設計的思想,給予了使用者更多的自定義條件,而不是一味的寫死。程式碼很簡單,思想很重要!

Spring Security技術棧開發企業級認證與授權系列文章列表:

示例程式碼下載地址:

專案已經上傳到碼雲,歡迎下載,內容所在資料夾為chapter009

相關推薦

Spring Security技術開發企業級認證授權開發圖形驗證介面

在設計登入模組的時候,圖形驗證碼基本上都是標配,本篇部落格重點介紹開發可重用的圖形驗證碼介面,該介面支援使用者自定義配置,比如驗證碼的長度、驗證碼圖形的寬度和高度等資訊。 本文的目標是開發一個圖形驗證碼介面,該驗證碼支援使用者自定義長度,以及生成圖片後

Spring Security技術開發企業級認證授權使用Filter、Interceptor和AOP攔截REST服務

一般情況,在訪問RESTful風格的API之前,可以對訪問行為進行攔截,並做一些邏輯處理,本文主要介紹三種攔截方式,分別是:過濾器Filter、攔截器Interceptor以及面向切面的攔截方式AOP。 一、使用過濾器Filter進行攔截 使用過

Spring Security技術開發企業級認證授權Spring Security的基本執行原理個性化登入實現

正如你可能知道的兩個應用程式的兩個主要區域是“認證”和“授權”(或者訪問控制)。這兩個主要區域是Spring Security的兩個目標。“認證”,是建立一個他宣告的主題的過程(一個“主體”一般是指使用者,裝置或一些可以在你的應用程式中執行動作的其他系統)

Spring Security技術開發企業級認證授權使用Swagger自動生成API文件

由於Spring Boot能夠快速開發、便捷部署等特性,相信有很大一部分Spring Boot的使用者會用來構建RESTful API。而我們構建RESTful API的目的通常都是由於多終端的原因,這些終端會共用很多底層業務邏輯,因此我們會抽象出這樣一層

Spring Security技術開發企業級認證授權環境搭建

Spring Security是一個能夠為基於Spring的企業應用系統提供宣告式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Contr

Spring Security技術開發企業級認證授權十一開發簡訊驗證登入

簡訊登入也是一種常見的登入方式,但是簡訊登入的方式並沒有整合到Spring Security中,所以往往還需要我們自己開發簡訊登入邏輯,將其整合到Spring Security中,使用Spring Security來進行校驗。本文將介紹開發簡訊登入的方法,

Spring Security技術開發企業級認證授權

iyu 復雜 sha 日誌 開發app 一個 核心概念 並發 自動 Spring Security技術棧開發企業級認證與授權網盤地址:https://pan.baidu.com/s/1mj8u6JQ 密碼: 92rp備用地址(騰訊微雲):https://share.weiy

Spring Security技術開發企業級認證授權 Spring Security開發安全的REST服務

第1章 課程導學 介紹課程內容、課程特點,使用的主要技術棧,以及學習課程所需的前置知識 1-1 導學 第2章 開始開發 安裝開發工具,介紹專案程式碼結構並搭建,基本的依賴和引數設定,開發hello world 2-1 開發環境安裝 2-2 程式碼結構介紹 2-3

.net core 認證授權

前言 .net core web並不是一個非常新的架構,很多文章提及到認證與授權這個過程,但是一般都會提及到裡面的方法怎麼用的,而不是模擬一個怎樣的過程,所以我打算記錄自己的理解。 什麼是認證?我們大學畢業有學士證書和畢業證書,來證明你是一個學士。 什麼是授權,比如說你被認證是我的朋友後,你可以拿著這個身份,

.net core 認證授權

前言 這篇緊接著一來寫的,在第一篇中介紹了認證與授權,同時提出了這套機制其實就是模擬現實中的認證與授權。 同樣這篇介紹在這套機制下,使用者資訊管理機制?這裡就會問了,上一篇中認證和授權不是都ok了嗎,怎麼會有一個管理機制呢?當然並不一定要使用下面這套機制,但是給了我們很大的啟發。 在上一結中我們頒發證書是這樣

.net core 認證授權

前言 在寫三上是在一的基礎上寫的,所以有沒有看過二是沒得關係的,在一中介紹了認證與授權,但是沒有去介紹拿到證書後怎樣去驗證授權。 概念性東西:在這套機制中,把這個許可權認證呢,稱作為policy。這個policy是怎麼樣的過程呢? 就像我前面說的,證書也認證了,policy做的是檢查你的證書中是否符合我心中的

Angular SPA基於Ocelot API閘道器IdentityServer4的身份認證授權

在上一講中,我們已經完成了一個完整的案例,在這個案例中,我們可以通過Angular單頁面應用(SPA)進行登入,然後通過後端的Ocelot API閘道器整合IdentityServer4完成身份認證。在本講中,我們會討論在當前這種架構的應用程式中,如何完成使用者授權。 回顧 《Angular SPA基於Oc

Spring-Security】【1】認證授權

部分 完整 業務 代碼 參數 web 用戶訪問 設置 管理權限 【認證】 憑據為基礎的認證: 當你登錄 e-mail 賬號時,你可能提供你的用戶名和密碼。E-mail的提供商會將你的用戶名與數據中的記錄進行匹配,並驗證你提供的密碼與對應的記錄是不是匹配。這些憑證(用戶名和

Spring Boot 揭秘實戰 應用監控篇 - HTTP 健康監控

don 此外 final 監控 blog jms 例如 簡單的 3.0 文章目錄 1. 內置 HealthIndicator 監控檢測 2. 自定義 HealthIndicator 監控檢測 3. 源代碼 Health 信息是從 ApplicationContext

2016-06-26 發布 支付系統開發的實踐思考

接口 簡單的 單向 new 成了 異步通知 平臺 應收 技術分享 通常我們在開發手機 app 或網站時都會涉及到支付相關的業務場景,用戶只需要簡單的點擊下按鈕並輸入密碼,就完成了整個支付過程。那麽今天我們就來簡單聊一下一個完整的支

Spring Cloud 基於Spring Boot 2.x的服務註冊發現Eureka

一.Spring Cloud 簡介        Spring Cloud為開發人員提供了快速構建分散式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智慧路由,微代理,控制匯流排,一次性令牌,全域性鎖定,領導選舉,分散式 會話,群集狀態)。 分散式系統的協調導致鍋

Android開發中佈局元件—— padding margin 的區別

在 Android開發中我們會設定某個檢視相對於別的檢視的距離,這時我們就要用到 margin 和 padding ,但是有時候很容易把這兩個屬性弄混淆,那我們就看看他們的區別。 外邊距(margin): 屬於佈局引數,決定兩個元件之間的距離。作用於多個元件之間。 內邊距(

Android開發中佈局元件—— 螢幕尺寸單位dp,px,sp的探究

在Android開發中,常用的尺寸單位有 dp , px , sp 。當然還有其他的單位如 pt , mm 等,不過這些都是不常用,所以我們重點來探究一下 dp , px , sp 這三個常用的單位。 px 英文 pixel 的縮寫,即畫素。無論螢幕密度為多少,一個畫素單位對應

Spring設計思想》AOP設計思想原理圖文並茂 侵立刪

轉自:https://mp.weixin.qq.com/s/1p2XSfhM1V5CcWro6PZEwQ   前言   Spring 提供了AOP(Aspect Oriented Programming) 的支援, 那麼,什麼是AOP呢?本文將通過一個另外一個角度

Android開發Linux開發的區別聯絡入門

1、Android的目錄路徑等不明,Linux程式碼如何移植進Android相應目錄不知; 2、目前Linux核心程式碼放置在\\192.168.1.190\share\android\kernel_imx; 3、安卓下編譯Linux核心的方法(PC機使用ssh除錯): #