前言
successHandler和failureHandler是Spring Security中兩個較爲強大的用來處理登錄成功和失敗的回調函數,通過它們兩個我們就可以自定義一些前後端數據的交互。
successHandler
該方法有三個參數
req:相當與HttpServletRequest
res:相當與HttpServletRespose
authentication:這裏保存了我們登錄後的用戶信息
進行如下配置
.successHandler((req, resp, authentication) -> {
Object principal = authentication.getPrincipal();
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
})
配置類代碼
package com.scexample.sc.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("xiaoming")
.password("123456").roles("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個是用來忽略一些url地址,對其不進行校驗,通常用在一些靜態文件中。
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/aaa.html")
.loginProcessingUrl("/logintest")
.usernameParameter("name")
.passwordParameter("passwd")
.successHandler((req, res, authentication) -> {
Object principal = authentication.getPrincipal();
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(new ObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
})
.permitAll()
.and()
.csrf().disable()
);
}
}
再次登錄後
failureHandler
該方法有三個參數
req:相當與HttpServletRequest
res:相當與HttpServletRespose
e:這裏保存了我們登錄失敗的原因
異常種類:
LockedException 賬戶鎖定
CredentialsExpiredException 密碼過期
AccountExpiredException 賬戶過期
DisabledException 賬戶被禁止
BadCredentialsException 用戶名或者密碼錯誤
.failureHandler((req, res, e) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(e.getMessage());
out.flush();
out.close();
})
配置類代碼:
package com.scexample.sc.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("xiaoming")
.password("123456").roles("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個是用來忽略一些url地址,對其不進行校驗,通常用在一些靜態文件中。
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/aaa.html")
.loginProcessingUrl("/logintest")
.usernameParameter("name")
.passwordParameter("passwd")
.successHandler((req, res, authentication) -> {
Object principal = authentication.getPrincipal();
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(new ObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
})
.failureHandler((req, res, e) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(e.getMessage());
out.flush();
out.close();
})
.permitAll()
.and()
.csrf().disable()
}
}
未認證處理方法
spring security默認情況下,如果認證不成功,直接重定向到登錄頁面。
但是項目中,我們有的時候不需要這樣,我們需要在前端進行判斷 ,然後再決定進行其他的處理,那我們就可以用authenticationEntryPoint這個接口進行自定義了,取消它的默認重定向行爲。
該方法有三個參數
req:相當與HttpServletRequest
res:相當與HttpServletRespose
authException:指的就是我們未認證的exception
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint((req, res, authException) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("檢測到未登錄狀態,請先登錄");
out.flush();
out.close();
}
配置類代碼
package com.scexample.sc.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("xiaoming")
.password("123456").roles("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個是用來忽略一些url地址,對其不進行校驗,通常用在一些靜態文件中。
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/aaa.html")
.loginProcessingUrl("/logintest")
.usernameParameter("name")
.passwordParameter("passwd")
.successHandler((req, res, authentication) -> {
Object principal = authentication.getPrincipal();
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(new ObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
})
.failureHandler((req, res, e) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(e.getMessage());
out.flush();
out.close();
})
.permitAll()
.and()
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint((req, res, authException) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("檢測到未登錄狀態,請先登錄");
out.flush();
out.close();
}
);
}
}
註銷登錄
.logoutSuccessHandler((req, res, authentication) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("註銷成功");
out.flush();
out.close();
})
配置類代碼:
package com.scexample.sc.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.PrintWriter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("xiaoming")
.password("123456").roles("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個是用來忽略一些url地址,對其不進行校驗,通常用在一些靜態文件中。
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/aaa.html")
.loginProcessingUrl("/logintest")
.usernameParameter("name")
.passwordParameter("passwd")
.successHandler((req, res, authentication) -> {
Object principal = authentication.getPrincipal();
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(new ObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
})
.failureHandler((req, res, e) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write(e.getMessage());
out.flush();
out.close();
})
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler((req, res, authentication) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("註銷成功");
out.flush();
out.close();
})
.permitAll()
.and()
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint((req, res, authException) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("檢測到未登錄狀態,請先登錄");
out.flush();
out.close();
}
);
}
}