最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring security4 添加驗證碼的示例代碼

 更新時間:2018年02月01日 11:37:04   作者:眉宇下的小格調(diào)  
本篇文章主要介紹了spring security4 添加驗證碼的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

spring security是一個很大的模塊,本文中只涉及到了自定義參數(shù)的認證。spring security默認的驗證參數(shù)只有username和password,一般來說都是不夠用的。由于時間過太久,有些忘,可能有少許遺漏。好了,不廢話。
spring以及spring security配置采用javaConfig,版本依次為4.2.5,4.0.4
總體思路:自定義EntryPoint,添加自定義參數(shù)擴展AuthenticationToken以及AuthenticationProvider進行驗證。

首先定義EntryPoint:

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
  public MyAuthenticationEntryPoint(String loginFormUrl) {
    super(loginFormUrl);
  }
  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
    super.commence(request, response, authException);
  }
}

接下來是token,validCode是驗證碼參數(shù):

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
public class MyUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
  private String validCode;
  public MyUsernamePasswordAuthenticationToken(String principal, String credentials, String validCode) {
    super(principal, credentials);
    this.validCode = validCode;
  }
  public String getValidCode() {
    return validCode;
  }
  public void setValidCode(String validCode) {
    this.validCode = validCode;
  }
}

繼續(xù)ProcessingFilter,

import com.core.shared.ValidateCodeHandle;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class MyValidCodeProcessingFilter extends AbstractAuthenticationProcessingFilter {
  private String usernameParam = "username";
  private String passwordParam = "password";
  private String validCodeParam = "validateCode";
  public MyValidCodeProcessingFilter() {
    super(new AntPathRequestMatcher("/user/login", "POST"));
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
    String username = request.getParameter(usernameParam);
    String password = request.getParameter(passwordParam);
    String validCode = request.getParameter(validCodeParam);
    valid(validCode, request.getSession());
    MyUsernamePasswordAuthenticationToken token = new MyUsernamePasswordAuthenticationToken(username, password, validCode);
    return this.getAuthenticationManager().authenticate(token);
  }

  public void valid(String validCode, HttpSession session) {
    if (validCode == null) {
      throw new ValidCodeErrorException("驗證碼為空!");
    }
    if (!ValidateCodeHandle.matchCode(session.getId(), validCode)) {
      throw new ValidCodeErrorException("驗證碼錯誤!");
    }
  }
}

分別定義三個參數(shù),用于接收login表單過來的參數(shù),構(gòu)造方法給出了login的url以及需要post方式

接下來就是認證了,此處還沒到認證用戶名和密碼的時候,只是認證了驗證碼

下面是ValidateCodeHandle一個工具類以及ValidCodeErrorException:

import java.util.concurrent.ConcurrentHashMap;
public class ValidateCodeHandle {
  private static ConcurrentHashMap validateCode = new ConcurrentHashMap<>();
  public static ConcurrentHashMap getCode() {
    return validateCode;
  }

  public static void save(String sessionId, String code) {
    validateCode.put(sessionId, code);
  }

  public static String getValidateCode(String sessionId) {
    Object obj = validateCode.get(sessionId);
    if (obj != null) {
      return String.valueOf(obj);
    }
    return null;
  }

  public static boolean matchCode(String sessionId, String inputCode) {
    String saveCode = getValidateCode(sessionId);
    if (saveCode.equals(inputCode)) {
      return true;
    }
    return false;
  }
}

這里需要繼承AuthenticationException以表明它是security的認證失敗,這樣才會走后續(xù)的失敗流程

import org.springframework.security.core.AuthenticationException;
public class ValidCodeErrorException extends AuthenticationException {

  public ValidCodeErrorException(String msg) {
    super(msg);
  }
  public ValidCodeErrorException(String msg, Throwable t) {
    super(msg, t);
  }
}

接下來是Provider:

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
public class MyAuthenticationProvider extends DaoAuthenticationProvider {
  @Override
  public boolean supports(Class<?> authentication) {
    return MyUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  }

  @Override
  protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    Object salt = null;
    if (getSaltSource() != null) {
      salt = getSaltSource().getSalt(userDetails);
    }
    if (authentication.getCredentials() == null) {
      logger.debug("Authentication failed: no credentials provided");
      throw new BadCredentialsException("用戶名或密碼錯誤!");
    }
    String presentedPassword = authentication.getCredentials().toString();
    if (!this.getPasswordEncoder().isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
      logger.debug("Authentication failed: password does not match stored value");

      throw new BadCredentialsException("用戶名或密碼錯誤!");
    }

  }
}

其中supports方法指定使用自定義的token,additionalAuthenticationChecks方法和父類的邏輯一模一樣,我只是更改了異常返回的信息。

接下來是處理認證成功和認證失敗的handler

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FrontAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
  public FrontAuthenticationSuccessHandler(String defaultTargetUrl) {
    super(defaultTargetUrl);
  }

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    super.onAuthenticationSuccess(request, response, authentication);
  }
}
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FrontAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  public FrontAuthenticationFailureHandler(String defaultFailureUrl) {
    super(defaultFailureUrl);
  }

  @Override
  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    super.onAuthenticationFailure(request, response, exception);
  }
}

最后就是最重要的security config 了:

import com.service.user.CustomerService;
import com.web.filter.SiteMeshFilter;
import com.web.mySecurity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
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.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
import org.springframework.web.filter.CharacterEncodingFilter;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends AbstractSecurityWebApplicationInitializer {

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new StandardPasswordEncoder("MD5");
  }

  @Autowired
  private CustomerService customerService;

  @Configuration
  @Order(1)
  public static class FrontendWebSecurityConfigureAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyValidCodeProcessingFilter myValidCodeProcessingFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable() 
          .authorizeRequests()
          .antMatchers("/user/login", "/user/logout").permitAll()
          .anyRequest().authenticated()
          .and()
          .addFilterBefore(myValidCodeProcessingFilter, UsernamePasswordAuthenticationFilter.class)
          .formLogin()
          .loginPage("/user/login")
          .and()
          .logout()
          .logoutUrl("/user/logout")
          .logoutSuccessUrl("/user/login");
    }

  }

  @Bean(name = "frontAuthenticationProvider")
  public MyAuthenticationProvider frontAuthenticationProvider() {
    MyAuthenticationProvider myAuthenticationProvider = new MyAuthenticationProvider();
    myAuthenticationProvider.setUserDetailsService(customerService);
    myAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    return myAuthenticationProvider;
  }

  @Bean
  public AuthenticationManager authenticationManager() {
    List<AuthenticationProvider> list = new ArrayList<>();
    list.add(frontAuthenticationProvider());
    AuthenticationManager authenticationManager = new ProviderManager(list);
    return authenticationManager;
  }

  @Bean
  public MyValidCodeProcessingFilter myValidCodeProcessingFilter(AuthenticationManager authenticationManager) {
    MyValidCodeProcessingFilter filter = new MyValidCodeProcessingFilter();
    filter.setAuthenticationManager(authenticationManager);
    filter.setAuthenticationSuccessHandler(frontAuthenticationSuccessHandler());
    filter.setAuthenticationFailureHandler(frontAuthenticationFailureHandler());
    return filter;
  }

  @Bean
  public FrontAuthenticationFailureHandler frontAuthenticationFailureHandler() {
    return new FrontAuthenticationFailureHandler("/user/login");
  }

  @Bean
  public FrontAuthenticationSuccessHandler frontAuthenticationSuccessHandler() {
    return new FrontAuthenticationSuccessHandler("/front/test");
  }

  @Bean
  public MyAuthenticationEntryPoint myAuthenticationEntryPoint() {
    return new MyAuthenticationEntryPoint("/user/login");
  }
}

首先是一個加密類的bean,customerService是一個簡單的查詢用戶

@Service("customerService")
public class CustomerServiceImpl implements CustomerService {

  @Autowired
  private UserDao userDao;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    return userDao.findCustomerByUsername(username);
  }
}

 下來就是FrontendWebSecurityConfigureAdapter了,重寫了configure方法,先禁用csrf, 開啟授權(quán)請求authorizeRequests(),其中”/user/login”, “/user/logout”放過權(quán)限驗證, 其他請求需要進行登錄認證, 然后是addFilterBefore(),把我自定義的myValidCodeProcessingFilter添加到security默認的UsernamePasswordAuthenticationFilter之前,也就是先進行我的自定義參數(shù)認證, 然后是formLogin(),配置登錄url以及登出url,登錄登出url都需要進行controller映射,也就是要自己寫controller。
接下來就是AuthenticationProvider,AuthenticationManager,ProcessingFilter,AuthenticationFailureHandler,AuthenticationSuccessHandler,EntryPoint的bean顯示聲明。

下面是login.jsp

<body>
<div class="login_div">
  <form:form autocomplete="false" commandName="userDTO" method="post">
    <div>
      <span class="error_tips"><b>${SPRING_SECURITY_LAST_EXCEPTION.message}</b></span>
    </div>
    username:<form:input path="username" cssClass="form-control"/><br/>
    password:<form:password path="password" cssClass="form-control"/><br/>
    validateCode:<form:input path="validateCode" cssClass="form-control"/>
    <label>${validate_code}</label>
    <div class="checkbox">
      <label>
        <input type="checkbox" name="remember-me"/>記住我
      </label>
    </div>
    <input type="submit" class="btn btn-primary" value="submit"/>
  </form:form>
</div>
</body>

 驗證碼驗證失敗的時候拋出的是ValidCodeErrorException,由于它繼承AuthenticationException,security在驗證的時候遇到AuthenticationException就會觸發(fā)AuthenticationFailureHandler,上面的bean中聲明了認證失敗跳轉(zhuǎn)到登錄url,所以login.jsp里面有${SPRING_SECURITY_LAST_EXCEPTION.message}獲取我認證時拋出異常信息,能友好的提示用戶。

整個自定義security驗證流程就走完了

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

相關(guān)文章

  • Spring Bean三種注入方式詳解

    Spring Bean三種注入方式詳解

    本篇文章主要介紹了Spring Bean三種注入方式詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • 詳解如何通過Java實現(xiàn)類似Nginx代理

    詳解如何通過Java實現(xiàn)類似Nginx代理

    最近遇到一個問題,在內(nèi)網(wǎng)環(huán)境中部署的項目需要調(diào)用外網(wǎng)完成一些應(yīng)用,一般情況我們可以通過增加一臺機器,部署到可以訪問外網(wǎng)的服務(wù)器上,然后內(nèi)網(wǎng)直接連接該機器通過Nginx進行代理即可,所以本文介紹了如何通過Java實現(xiàn)類似Nginx代理,需要的朋友可以參考下
    2024-08-08
  • Java中的字符串用法小結(jié)

    Java中的字符串用法小結(jié)

    這篇文章主要介紹了Java中的字符串用法,實例總結(jié)了java中關(guān)于字符串操作的各種常用的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • Spring RestTemplate具體使用詳解

    Spring RestTemplate具體使用詳解

    這篇文章主要介紹了Spring RestTemplate具體使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • 如何解決Springboot?Dao注入失敗的問題

    如何解決Springboot?Dao注入失敗的問題

    這篇文章主要介紹了如何解決Spring?boot?Dao注入失敗的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 使用Java解析JSON數(shù)據(jù)并提取特定字段的實現(xiàn)步驟(以提取mailNo為例)

    使用Java解析JSON數(shù)據(jù)并提取特定字段的實現(xiàn)步驟(以提取mailNo為例)

    在現(xiàn)代軟件開發(fā)中,處理JSON數(shù)據(jù)是一項非常常見的任務(wù),無論是從API接口獲取數(shù)據(jù),還是將數(shù)據(jù)存儲為JSON格式,解析和提取JSON中的特定字段都是開發(fā)人員需要掌握的基本技能,本文將以一個實際案例為例,詳細介紹如何使用Java解析JSON數(shù)據(jù)并提取其中的mailNo字段
    2025-01-01
  • 程序包org.springframework不存在的解決辦法

    程序包org.springframework不存在的解決辦法

    這篇文章主要介紹了程序包org.springframework不存在的解決辦法,在使用IDEA創(chuàng)建SpringBoot項目時,剛打開無法正常運行,本文通過圖文結(jié)合的方式給大家介紹的非常詳細,具有一定參考價值,需要的朋友可以參考下
    2024-07-07
  • java對象持久化保存的方法詳解

    java對象持久化保存的方法詳解

    這篇文章主要介紹了java對象持久化保存的方法詳解,在java應(yīng)用開發(fā)的過程中,經(jīng)常遇到需要持久保存java對象的情況,比如:用戶信息、博客評論內(nèi)容等等,本文針對java對象的持久化保存方法進行討論,簡述各個方法的優(yōu)劣,需要的朋友可以參考下
    2023-07-07
  • Springboot項目基于Devtools實現(xiàn)熱部署步驟詳解

    Springboot項目基于Devtools實現(xiàn)熱部署步驟詳解

    這篇文章主要介紹了Springboot項目基于Devtools實現(xiàn)熱部署,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Mybatis逆工程jar包的修改和打包

    Mybatis逆工程jar包的修改和打包

    這篇文章主要介紹了Mybatis逆工程jar包的修改和打包的相關(guān)資料,需要的朋友可以參考下
    2016-06-06

最新評論

肇州县| 房山区| 通化市| 鄱阳县| 唐河县| 锡林郭勒盟| 津南区| 永兴县| 江都市| 仁寿县| 霸州市| 句容市| 平度市| 伊通| 滕州市| 吉木乃县| 扎囊县| 泰州市| 信宜市| 永川市| 阿合奇县| 依兰县| 抚顺市| 开原市| 牡丹江市| 砀山县| 延寿县| 维西| 永仁县| 广州市| 大悟县| 桦南县| 凌海市| 乌恰县| 九龙县| 南丹县| 桂平市| 大石桥市| 两当县| 资兴市| 常熟市|