SpringSecurity實(shí)現(xiàn)自定義登錄方式
自定義登錄
- 定義Token
- 定義Filter
- 定義Provider
- 配置類(lèi)中定義登錄的接口
1.自定義AuthenticationToken
public class EmailAuthenticationToken extends UsernamePasswordAuthenticationToken{ public EmailAuthenticationToken(Object principal, Object credentials) { super(principal, credentials); } public EmailAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) { super(principal, credentials, authorities); } }
2.自定義AuthenticationFilter
public class EmailAuthenticationFilter extends AbstractAuthenticationProcessingFilter { private static final String EMAIL = "email"; private static final String EMAIL_CODE = "emailCode"; private boolean postOnly = true; public EmailAuthenticationFilter(RequestMatcher requestMatcher) { super(requestMatcher); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (this.postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } else { Map<String, String> map = new ObjectMapper().readValue(request.getInputStream(), Map.class); String email = map.get(EMAIL); email = email != null ? email : ""; email = email.trim(); String emailCode = map.get(EMAIL_CODE); emailCode = emailCode != null ? emailCode : ""; EmailAuthenticationToken emailAuthenticationToken = new EmailAuthenticationToken(email, emailCode); this.setDetails(request, emailAuthenticationToken); return this.getAuthenticationManager().authenticate(emailAuthenticationToken); } } protected void setDetails(HttpServletRequest request, EmailAuthenticationToken authRequest) { authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); } }
3.自定義AuthenticationProvider
public class EmailAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { EmailAuthenticationToken emailAuthenticationToken = (EmailAuthenticationToken) authentication; String code = emailAuthenticationToken.getCode(); String email = (String) emailAuthenticationToken.getPrincipal(); if (email.equals("205564122@qq.com") && code.equals("1234")) { SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("wuyu"); return new EmailAuthenticationToken(email, null, List.of(simpleGrantedAuthority)); } throw new InternalAuthenticationServiceException("認(rèn)證失敗"); } @Override public boolean supports(Class<?> authentication) { return EmailAuthenticationToken.class.isAssignableFrom(authentication); } }
4.定義SecurityConfig配置類(lèi)
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private StringRedisTemplate stringRedisTemplate; @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.cors().disable(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.authorizeHttpRequests().anyRequest().permitAll(); http.logout().logoutSuccessHandler(logoutSuccessHandler()); // 配置郵箱登錄 EmailAuthenticationFilter emailAuthenticationFilter = new EmailAuthenticationFilter(new AntPathRequestMatcher("/login/email", "POST")); emailAuthenticationFilter.setAuthenticationManager(authenticationManagerBean()); emailAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler()); emailAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler()); http.addFilterBefore(emailAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.authenticationProvider(new EmailAuthenticationProvider()); } @Bean public AuthenticationSuccessHandler authenticationSuccessHandler() { return (request, response, authentication) -> { // 1.生成Token String token = UUID.randomUUID().toString(); // 2.將Token和用戶信息存入redis stringRedisTemplate.opsForValue().set(AuthConstants.TOKEN_PREFIX + token, JSON.toJSONString(authentication.getPrincipal()), AuthConstants.TOKEN_DURATION); // 3.返回Token response.setContentType(ResponseConstants.APPLICATION_JSON); PrintWriter writer = response.getWriter(); writer.write(JSON.toJSONString(Result.success(token))); writer.flush(); writer.close(); }; } @Bean public AuthenticationFailureHandler authenticationFailureHandler() { return (request, response, exception) -> { response.setContentType(ResponseConstants.APPLICATION_JSON); PrintWriter writer = response.getWriter(); writer.write(JSON.toJSONString(Result.fail(exception.getMessage()))); writer.flush(); writer.close(); }; } @Bean public LogoutSuccessHandler logoutSuccessHandler() { return (request, response, authentication) -> { String authorization = request.getHeader(AuthConstants.AUTHORIZATION); authorization = authorization.replace(AuthConstants.BEARER, ""); stringRedisTemplate.delete(AuthConstants.TOKEN_PREFIX + authorization); PrintWriter writer = response.getWriter(); writer.write(JSON.toJSONString(Result.success())); writer.flush(); writer.close(); }; } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實(shí)體對(duì)象與Map之間的轉(zhuǎn)換工具類(lèi)代碼實(shí)例
這篇文章主要介紹了java實(shí)體對(duì)象與Map之間的轉(zhuǎn)換工具類(lèi)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Springboot動(dòng)態(tài)切換數(shù)據(jù)源的具體實(shí)現(xiàn)與原理分析
目前有個(gè)需求,需要使用不同的數(shù)據(jù)源,例如某業(yè)務(wù)要用A數(shù)據(jù)源,另一個(gè)業(yè)務(wù)要用B數(shù)據(jù)源,所以下面這篇文章主要給大家介紹了關(guān)于Springboot動(dòng)態(tài)切換數(shù)據(jù)源的具體實(shí)現(xiàn)與原理分析,需要的朋友可以參考下2021-12-12SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測(cè)好用)
這篇文章主要介紹了SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測(cè)好用),在Spring?Boot?2.x中,整合了這兩個(gè)JTA的實(shí)現(xiàn)分別是Atomikos和Bitronix,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07SpringBoot如何使用feign實(shí)現(xiàn)遠(yuǎn)程接口調(diào)用和錯(cuò)誤熔斷
這篇文章主要介紹了SpringBoot如何使用feign實(shí)現(xiàn)遠(yuǎn)程接口調(diào)用和錯(cuò)誤熔斷,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Java中的SecretKeyFactory類(lèi)使用詳解
這篇文章主要介紹了Java中的SecretKeyFactory類(lèi)使用詳解,SecretKeyFactory表示私密密鑰的工廠,密鑰工廠用來(lái)將密鑰(類(lèi)型 Key 的不透明加密密鑰)轉(zhuǎn)換為密鑰規(guī)范(底層密鑰材料的透明表示形式),需要的朋友可以參考下2024-01-01詳解Maven倉(cāng)庫(kù)之本地倉(cāng)庫(kù)、遠(yuǎn)程倉(cāng)庫(kù)
這篇文章主要介紹了Maven倉(cāng)庫(kù)之本地倉(cāng)庫(kù)、遠(yuǎn)程倉(cāng)庫(kù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Spring創(chuàng)建bean對(duì)象三種方式代碼實(shí)例
這篇文章主要介紹了Spring創(chuàng)建bean對(duì)象三種方式代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07WebUploader實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了WebUploader實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03