欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring security自定義用戶認(rèn)證流程詳解

 更新時(shí)間:2020年03月11日 14:42:01   作者:我太難了008  
這篇文章主要介紹了Spring security自定義用戶認(rèn)證流程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

1.自定義登錄頁(yè)面

(1)首先在static目錄下面創(chuàng)建login.html

  注意:springboot項(xiàng)目默認(rèn)可以訪問resources/resources,resources/staic,resources/public目錄下面的靜態(tài)文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登錄頁(yè)面</title>
</head>
<body>
<form action="/auth/login" method="post">
  用戶名:<input type="text" name="username">
  <br/>
  密&emsp;碼:<input type="password" name="password">
  <br/>
  <input type="submit" value="登錄">
</form>
</body>
</html>

(2)在spring securiy配置類中做如下配置

@Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        // 指定自定義登錄頁(yè)面
        .loginPage("/login.html")
        // 登錄url
        .loginProcessingUrl("/auth/login")
        .and()
        .authorizeRequests()
        // 添加一個(gè)url匹配器,如果匹配到login.html,就授權(quán)
        .antMatchers("/login.html").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // 關(guān)閉spring security默認(rèn)的防csrf攻擊
        .csrf().disable();
  }

(3)測(cè)試

(4)存在的問題

<1>作為可以復(fù)用的登錄模塊,我們應(yīng)該提供個(gè)性化的登錄頁(yè)面,也就是說不能寫死只跳轉(zhuǎn)到login.html。

    此問題比較好解決,使用可配置的登錄頁(yè)面,默認(rèn)使用login.html即可。

<2> 請(qǐng)求跳轉(zhuǎn)到login.html登錄頁(yè)面,貌似沒有什么問題,但作為restful風(fēng)格的接口,一般響應(yīng)的都是json數(shù)據(jù)格式,尤其是app請(qǐng)求。

    解決思想:用戶發(fā)起數(shù)據(jù)請(qǐng)求 --> security判斷是否需要身份認(rèn)證 ----->跳轉(zhuǎn)到一個(gè)自定義的controller方法 ------>在該方法內(nèi)判斷是否是html發(fā)起的請(qǐng)求,如果是,就跳轉(zhuǎn)到login.html,如果不是,響應(yīng)一個(gè)json格式的數(shù)據(jù),說明錯(cuò)誤信息。

自定義Controller

@Slf4j
@RestController
public class LoginController {

  /**
   * 請(qǐng)求緩存
   */
  private RequestCache requestCache = new HttpSessionRequestCache();

  /**
   * 重定向工具類
   */
  private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

  /**
   * 如果配置的登錄頁(yè)就使用配置的登錄面,否則使用默認(rèn)的登錄頁(yè)面
   */
//  @Value("${xxxx:defaultLoginPage}")
//  private String standardLoginPage;
  private String standardLoginPage = "/login.html"; // 登錄頁(yè)

  /**
   * 用戶身份認(rèn)證方法
   */
  @GetMapping("/user/auth")
  @ResponseStatus(code = HttpStatus.UNAUTHORIZED) // 返回狀態(tài)
  public ResponseData login(HttpServletRequest request, HttpServletResponse response) throws IOException {
    SavedRequest savedRequest = requestCache.getRequest(request, response);
    if (savedRequest != null) {
      String targetUrl = savedRequest.getRedirectUrl();
      log.info("請(qǐng)求是:" + targetUrl);
      // 如果請(qǐng)求是以html結(jié)尾
      if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
        redirectStrategy.sendRedirect(request, response, standardLoginPage);
      }
    }
    return new ResponseData("該請(qǐng)求需要登錄,js拿到我的響應(yīng)數(shù)據(jù)后,是否需要跳轉(zhuǎn)到登錄頁(yè)面你自己看著辦吧?");
  }
}

spring security給該controller的login方法授權(quán)

@Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        // 先進(jìn)controller中去
        .loginPage("/user/auth")
        // 指定自定義登錄頁(yè)面
        .loginPage("/login.html")
        // 登錄url
        .loginProcessingUrl("/auth/login")
        .and()
        .authorizeRequests()
        // 該controller需要授權(quán)
        .antMatchers("/user/auth").permitAll()
        // 添加一個(gè)url匹配器,如果匹配到login.html,就授權(quán)
        .antMatchers("/login.html").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // 關(guān)閉spring security默認(rèn)的防csrf攻擊
        .csrf().disable();
  }

這樣子就行了?。。 ?/p>

2. 自定義登錄成功處理(返回json)

(1)實(shí)現(xiàn)AuthenticationSuccessHandler.java

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
  @Autowired
  private ObjectMapper objectMapper;
  /**
   * Called when a user has been successfully authenticated.
   * @param request
   * @param response
   * @param authentication
   * @throws IOException
   * @throws ServletException
   */
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    log.info("登錄成功?。?!");
    // 將登錄成功的信息寫到前端
    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
    response.getWriter().write(objectMapper.writeValueAsString(authentication));

  }
}

(2)修改security配置類

@Autowired
  private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        // 先進(jìn)controller中去
        .loginPage("/user/auth")
        // 指定自定義登錄頁(yè)面
        .loginPage("/login.html")
        // 登錄url
        .loginProcessingUrl("/auth/login")
        .successHandler(myAuthenticationSuccessHandler)
        .and()
        .authorizeRequests()
        // 該controller需要授權(quán)
        .antMatchers("/user/auth").permitAll()
        // 添加一個(gè)url匹配器,如果匹配到login.html,就授權(quán)
        .antMatchers("/login.html").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // 關(guān)閉spring security默認(rèn)的防csrf攻擊
        .csrf().disable();
  }

(3)測(cè)試

說明:authentication對(duì)象中包含的信息,會(huì)因?yàn)榈卿浄绞降牟煌l(fā)生改變

3.自定義登錄失敗處理(返回json)

  實(shí)現(xiàn)AuthenticationFailureHandler.java接口即可,跟登錄成敗處理配置一樣。

4.自定義登錄成功處理邏輯

 以上的登錄成功或失敗的返回的都是json,但是在某些情況下,就是存在著登錄成功或者失敗進(jìn)行頁(yè)面跳轉(zhuǎn)(spring security默認(rèn)的處理方式),那么這種返回json的方式就不合適了。所以,我們應(yīng)該做得更靈活,做成可配置的。

 對(duì)于登錄成功邏輯而言只需要對(duì)MyAuthenticationSuccessHandler.java稍做修改就行,代碼如下所示:

/**
 * SavedRequestAwareAuthenticationSuccessHandler spring security 默認(rèn)的成功處理器
 */
@Slf4j
@Component
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
  @Autowired
  private ObjectMapper objectMapper;

  /**
   * 配置的登錄方式
   */
//  @Value("${xxx:默認(rèn)方式}")
  private String loginType = "JSON";
  /**
   * Called when a user has been successfully authenticated.
   */
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    log.info("登錄成功!!!");

    // 如果配置的登錄方式是JSON,就返回json數(shù)據(jù)
    if ("JSON".equals(loginType)) {
      // 將登錄成功的信息寫到前端
      response.setContentType(MediaType.APPLICATION_JSON_VALUE);
      response.getWriter().write(objectMapper.writeValueAsString(authentication));
    } else { // 否則就使用默認(rèn)的跳轉(zhuǎn)方式
      super.onAuthenticationSuccess(request,response,authentication);
    }
  }
}

5.自定義登錄失敗處理邏輯

同登錄成功類似,具體代碼如下:

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  @Autowired
  private ObjectMapper objectMapper;

  /**
   * 配置的登錄方式
   */
//  @Value("${xxx:默認(rèn)方式}")
  private String loginType = "JSON";
  @Override
  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    log.info("登錄失?。。?!");

    // 如果配置的登錄方式是JSON,就返回json數(shù)據(jù)
    if ("JSON".equals(loginType)) {
      // 將登錄成功的信息寫到前端
      response.setStatus(HttpStatus.UNAUTHORIZED.value());
      response.setContentType(MediaType.APPLICATION_JSON_VALUE);
      response.getWriter().write(objectMapper.writeValueAsString(exception));
    } else { // 否則就使用默認(rèn)的跳轉(zhuǎn)方式,跳轉(zhuǎn)到一個(gè)錯(cuò)誤頁(yè)面
      super.onAuthenticationFailure(request,response,exception);
    }
  }
}
@Autowired
  private MySimpleUrlAuthenticationFailureHandler mySimpleUrlAuthenticationFailureHandler;
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        // 先進(jìn)controller中去
        .loginPage("/user/auth")
        // 指定自定義登錄頁(yè)面
        .loginPage("/login.html")
        // 登錄url
        .loginProcessingUrl("/auth/login")
        .successHandler(myAuthenticationSuccessHandler)
        .failureHandler(mySimpleUrlAuthenticationFailureHandler)
        .and()
        .authorizeRequests()
        // 該controller需要授權(quán)
        .antMatchers("/user/auth").permitAll()
        // 添加一個(gè)url匹配器,如果匹配到login.html,就授權(quán)
        .antMatchers("/login.html").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        // 關(guān)閉spring security默認(rèn)的防csrf攻擊
        .csrf().disable();
  }

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JAVA中 終止線程的方法介紹

    JAVA中 終止線程的方法介紹

    JAVA中 終止線程的方法介紹,需要的朋友可以參考一下
    2013-03-03
  • Java?Request獲取請(qǐng)求頭數(shù)據(jù)實(shí)例詳解

    Java?Request獲取請(qǐng)求頭數(shù)據(jù)實(shí)例詳解

    在開發(fā)中我們經(jīng)常需要獲取用戶IP地址,通過地址來實(shí)現(xiàn)一些功能,下面這篇文章主要給大家介紹了關(guān)于Java中Request獲取請(qǐng)求頭數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • hibernate屬性級(jí)別注解實(shí)例代碼

    hibernate屬性級(jí)別注解實(shí)例代碼

    這篇文章主要介紹了hibernate屬性級(jí)別注解實(shí)例代碼,涉及屬性級(jí)別注釋添加方式及種類,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • Java?Spring?boot日期和時(shí)間統(tǒng)一設(shè)置三種方法

    Java?Spring?boot日期和時(shí)間統(tǒng)一設(shè)置三種方法

    時(shí)間和日期的統(tǒng)一設(shè)置在項(xiàng)目中經(jīng)常是會(huì)遇到的,下面這篇文章主要給大家介紹了關(guān)于Java?Spring?boot日期和時(shí)間統(tǒng)一設(shè)置的三種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • 最新評(píng)論