java security 详解_SpringSecurity基础功能详解

本文详细介绍了Spring Security的基础功能,包括默认登录、自定义用户认证、登录页面、登录成功和失败处理、图形验证码、记住我功能、Session管理以及退出操作等。通过示例代码展示了如何配置和自定义各个功能,如使用UserDetailsService实现认证,自定义登录页面和处理逻辑,以及配置记住我功能和Session超时策略。
摘要由CSDN通过智能技术生成

本篇目录:

一、默认情况

二、自定义用户认证

三、自定义用户登录页面

四、自定义登录成功、失败处理

五、图形验证码

六、记住我功能

七、Session管理

八、退出操作

首先说明本文所用的SpringSecurity版本是2.0.4.RELEASE。下面逐个功能介绍。

一、默认情况

1、构建与配置

1)pom.xml

org.springframework.boot

spring-boot-starter-security

2)application.properties

无需配置

3)UserController.java

@GetMapping("/user")public Listquery(){

List users = new ArrayList();

users.add(new User("1","张三","123456",newDate()));returnusers;

}

2、启动与测试

1)启动程序,控制台打印出默认密码:“Using generated security password: 15a189e8-accb-407a-ad81-2283c8b3bdbf”

d2a360b57bb76331bf654608ffc6f7cb.png

2)浏览器输入:http://localhost:8080/user,跳转到表单登录页面

97beb89611d2c02e0c74b4afe572af82.png

3)输入默认用户名user与默认用户密码15a189e8-accb-407a-ad81-2283c8b3bdbf,访问到数据

31a172aef675ee93955a0b87e417d72f.png

二、 自定义用户认证

1、实现UserDetailsService接口

@Componentpublic class MyUserDetailsService implementsUserDetailsService{

@AutowiredprivatePasswordEncoder passwordEncoder;

@Overridepublic UserDetails loadUserByUsername(String username) throwsUsernameNotFoundException {return new User(username, passwordEncoder.encode("123456"),

AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

}

@BeanpublicPasswordEncoder passwordEncoder() {return newBCryptPasswordEncoder();

}

}

2、说明

1)认证时用户名任意,密码是12345,输错密码,提示坏的凭证。

2)必须加密,实际项目中,将密码passwordEncoder.encode("123456")进行加密,写入数据库。

3)构造函数四个true假如为false依次代表:用户已失效;用户帐号已过期;用户凭证已过期;用户帐号已被锁定。

return new User(username, passwordEncoder.encode("123456"),true,true,true,true,

AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

三、自定义用户登录页面

登录页面/static/login.html

登录

标准登录页面

表单登录

用户名
密码
登录

1、loginPage指定登录页面

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.formLogin()

.loginPage("/login.html")//指定登录页面

.loginProcessingUrl("/authentication/form");//指定登录页面中表单的url

http.authorizeRequests()

.antMatchers("/login.html").permitAll()//该路径不需要身份认证

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

}

2、loginPage指定Controller,自定义判断

1)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.formLogin()

.loginPage("/authentication/require")//指定需要认证时路径

.loginProcessingUrl("/authentication/form");//指定登录页面中表单的url

http.authorizeRequests()

.antMatchers("/login.html").permitAll()//该路径不需要身份认证

.antMatchers("/authentication/require").permitAll()

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

}

2)SecurityController.java

@RestControllerpublic classSecurityController {private RequestCache requestCache=newHttpSessionRequestCache();private RedirectStrategy redirectStrategy=newDefaultRedirectStrategy();

@RequestMapping("/authentication/require")

@ResponseStatus(code=HttpStatus.UNAUTHORIZED)public SimpleResponse requireAuthentication(HttpServletRequest request,HttpServletResponse response) throwsException {

SavedRequest savedRequest=requestCache.getRequest(request, response);if(savedRequest!=null) {

String targetUrl=savedRequest.getRedirectUrl();

System.out.println("引发跳转的请求是:"+targetUrl);if(StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {

redirectStrategy.sendRedirect(request, response,"/login.html");

}

}return new SimpleResponse("访问的服务需要身份认证,请引导用户到登录页");

}

}

3)index.html

index

index测试页面

测试输入http://localhost:8080/index.html,跳转到登录页,输入用户名、密码跳转到index.html页面。

测试输入http://localhost:8080/user,页面打印出{"content":"访问的服务需要身份认证,请引导用户到登录页"}。

四、自定义登录成功、失败处理

1、构建与配置

1)pom.xml添加处理json依赖

org.codehaus.jackson

jackson-mapper-asl

1.9.13

2)AuthenticationSuccessHandler.java

@Component("authenticationSuccessHandler")public class AuthenticationSuccessHandler extendsSavedRequestAwareAuthenticationSuccessHandler{

@AutowiredprivateSecurityProperties securityProperties;private ObjectMapper objectMapper=newObjectMapper();

@Overridepublic voidonAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,

Authentication authentication)throwsIOException, ServletException {

System.out.println("登录成功!");if(LoginResponseType.JSON.equals(securityProperties.getLoginType())) {//如果配置了JSON格式,返回如下信息

response.setContentType("application/json;charset=UTF-8");

response.getWriter().write(objectMapper.writeValueAsString(authentication));

}else {//否则执行默认的方式,跳转原请求地址

super.onAuthenticationSuccess(request, response, authentication);

}

}

}

3)AuthenticationFailureHandler.java

@Component("authenticationFailureHandler")public class AuthenticationFailureHandler extendsSimpleUrlAuthenticationFailureHandler {

@AutowiredprivateSecurityProperties securityProperties;private ObjectMapper objectMapper=newObjectMapper();

@Overridepublic voidonAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,

AuthenticationException exception)throwsIOException, ServletException {

System.out.println("登录失败!");if(LoginResponseType.JSON.equals(securityProperties.getLoginType())) {

response.setContentType("application/json;charset=UTF-8");

response.getWriter().write(objectMapper.writeValueAsString(newSimpleResponse(exception.getMessage())));

}else{//执行默认的方式,跳转loginPage配置的地址super.onAuthenticationFailure(request, response, exception);

}

}

}

4)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

@Autowiredprivate AuthenticationSuccessHandler authenticationSuccessHandler;

@Autowired

privateAuthenticationFailureHandler authenticationFailureHandler;

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.formLogin()

.loginPage("/authentication/require")//指定需要认证时路径

.loginProcessingUrl("/authentication/form")//指定登录页面中表单的url

.successHandler(authenticationSuccessHandler)//认证成功后自定义处理逻辑

.failureHandler(authenticationFailureHandler);//认证失败后自定义处理逻辑

http.authorizeRequests()

.antMatchers("/login.html").permitAll()//该路径不需要身份认证

.antMatchers("/authentication/require").permitAll()

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

}

5)application.properties

project.security.loginType=REDIRECT

6)SecurityCoreConfig.java

@Configuration

@EnableConfigurationProperties(SecurityProperties.class)public classSecurityCoreConfig {

}

7)LoginResponseType.java

public enumLoginResponseType {

REDIRECT,

JSON

}

8)SecurityProperties.java

@ConfigurationProperties(prefix="project.security")public classSecurityProperties {private LoginResponseType loginType=LoginResponseType.JSON;//默认JSON

publicLoginResponseType getLoginType() {returnloginType;

}public voidsetLoginType(LoginResponseType loginType) {this.loginType =loginType;

}

}

2、测试

1)application.properties中配置REDIRECT,输入localhost:8080/index.html,控制台打印如下信息,并跳转登录页

bdefe25829e6c48028bd503d83aa4fcb.png

1.1)输入错误密码,控制台打印如下信息,浏览器显示:{"content":"访问的服务需要身份认证,请引导用户到登录页"}

3ea752903b0bc07247e0798f117d9f38.png

1.2)输入正确密码,控制台打印“登录成功!”,浏览器跳转index.html,显示:index测试页面

2)application.properties中配置JSON,输入localhost:8080/user,控制台打印如下信息,

801c124cff25ccc6bed3b01bf0d14a34.png

浏览器显示:{"content":"访问的服务需要身份认证,请引导用户到登录页"}

2.1)浏览器输入:localhost:8080/index.html,控制台打印如下信息,并跳转登录页。

bdefe25829e6c48028bd503d83aa4fcb.png

2.3)输入错误密码,控制台打印“登录失败!”,浏览器显示:{"content":"坏的凭证"}

2.4)输入正确密码,控制台打印“登录成功!”,浏览器显示登录信息:

81d1d9a2ef7690399d61cb19c47ffc9c.png

问题:为什么会打印两次:“引发跳转的请求”?

五、图形验证码

1、构建与配置

1)ImageCode.java

public classImageCode{privateBufferedImage image;privateString code;privateLocalDateTime expireTime;publicBufferedImage getImage() {returnimage;

}public voidsetImage(BufferedImage image) {this.image =image;

}public ImageCode(BufferedImage image, String code, intexpireIn) {this.image =image;this.code =code;this.expireTime =LocalDateTime.now().plusSeconds(expireIn);

}publicString getCode() {returncode;

}public voidsetCode(String code) {this.code =code;

}publicLocalDateTime getExpireTime() {returnexpireTime;

}public voidsetExpireTime(LocalDateTime expireTime) {this.expireTime =expireTime;

}public booleanisExpried() {returnLocalDateTime.now().isAfter(expireTime);

}

}

2)ValidateCodeController.java

@RestControllerpublic classValidateCodeController {

@GetMapping("/code/image")public void createCode(HttpServletRequest request,HttpServletResponse response) throwsException {

ImageCode imageCode=createImageCode(request);

request.getSession().setAttribute("imageCodeSession", imageCode);

ImageIO.write(imageCode.getImage(),"JPEG", response.getOutputStream());

}privateImageCode createImageCode(HttpServletRequest request) {int width=67;int height=23;

BufferedImage image=newBufferedImage(width, height,BufferedImage.TYPE_INT_RGB);

Graphics g=image.getGraphics();

Random random=newRandom();

g.setColor(getRandColor(200,250));

g.fillRect(0,0, width, height);

g.setFont(new Font("TIME 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);

}

String sRand="";for(int i=0;i<4;i++) {

String rand=String.valueOf(random.nextInt(10));

sRand+=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,60);

}private Color getRandColor(int fc, intbc) {

Random random=newRandom();if(fc>255) {

fc=255;

}if(bc>255) {

bc=255;

}int r=fc+random.nextInt(bc-fc);int g=fc+random.nextInt(bc-fc);int b=fc+random.nextInt(bc-fc);return newColor(r,g,b);

}

}

3)ValidateCodeException.java

public class ValidateCodeException extendsAuthenticationException {private static final long serialVersionUID = 1L;publicValidateCodeException(String msg) {super(msg);

}

}

4)ValidateCodeFilter.java

@Componentpublic class ValidateCodeFilter extendsOncePerRequestFilter{

@AutowiredprivateAuthenticationFailureHandler authenticationFailureHandler;

@Overrideprotected voiddoFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throwsServletException, IOException {if(StringUtils.equals("http://localhost:8080/authentication/form",request.getRequestURL()+"") &&StringUtils.equalsIgnoreCase(request.getMethod(),"post")) {try{

validate(request);

}catch(ValidateCodeException e) {

authenticationFailureHandler.onAuthenticationFailure(request, response, e);return;

}

}

filterChain.doFilter(request, response);

}private voidvalidate(HttpServletRequest request){

ImageCode codeInSession= (ImageCode)request.getSession().getAttribute("imageCodeSession");

String codeInRequest= request.getParameter("imageCode");if(StringUtils.isBlank(codeInRequest)) {throw new ValidateCodeException("验证码的值不能为空");

}if (codeInSession == null) {throw new ValidateCodeException("验证码不存在");

}if(codeInSession.isExpried()) {

request.getSession().removeAttribute("imageCodeSession");throw new ValidateCodeException("验证码已过期");

}if (!StringUtils.equals(codeInSession.getCode(), codeInRequest)) {throw new ValidateCodeException("验证码不匹配");

}

request.getSession().removeAttribute("imageCodeSession");

}

}

5)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig2 extendsWebSecurityConfigurerAdapter{

@AutowiredprivateAuthenticationSuccessHandler authenticationSuccessHandler;

@AutowiredprivateAuthenticationFailureHandler authenticationFailureHandler;

@AutowiredprivateValidateCodeFilter validateCodeFilter;

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);//认证前添加验证码过滤器

http.formLogin()

.loginPage("/authentication/require")//指定需要认证时路径

.loginProcessingUrl("/authentication/form")//指定登录页面中表单的url

.successHandler(authenticationSuccessHandler)//认证成功后自定义处理逻辑

.failureHandler(authenticationFailureHandler);//认证失败后自定义处理逻辑

http.authorizeRequests()

.antMatchers("/login.html").permitAll()//该路径不需要身份认证

.antMatchers("/authentication/require").permitAll()

.antMatchers("/code/image").permitAll()//图片验证码

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

}

6)static/login.html

登录

标准登录页面

表单登录

用户名
密码
图片验证码image
登录

2、说明

1)验证码处理流程为:生成验证码->放在Session中->验证->清空Session

2)过滤器OncePerRequestFilter,每一次请求只进入一次该过滤器

六、记住我功能

1、构建与配置

1)pom.xml添加以下依赖

org.springframework.boot

spring-boot-starter-jdbc

mysql

mysql-connector-java

2)application.properties

project.security.loginType=REDIRECT

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3309/springsecurity

spring.datasource.username=root

spring.datasource.password=123456

3)login.html

登录

标准登录页面

表单登录

用户名
密码
图片验证码image
记住我
登录

4)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

@AutowiredprivateAuthenticationSuccessHandler authenticationSuccessHandler;

@AutowiredprivateAuthenticationFailureHandler authenticationFailureHandler;

@AutowiredprivateValidateCodeFilter validateCodeFilter;

@Autowiredprivate DataSource dataSource;

@Autowired

privateUserDetailsService userDetailsService;

@Overrideprotected void configure(HttpSecurity http) throwsException {

http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);//认证前添加验证码过滤器http.formLogin()

.loginPage("/authentication/require")//指定需要认证时路径

.loginProcessingUrl("/authentication/form")//指定登录页面中表单的url

.successHandler(authenticationSuccessHandler)//认证成功后自定义处理逻辑

.failureHandler(authenticationFailureHandler);//认证失败后自定义处理逻辑

http.rememberMe()//记住我

.tokenRepository(persistentTokenRepository())

.tokenValiditySeconds(60*60*1)//记住我1小时.userDetailsService(userDetailsService);

http.authorizeRequests()

.antMatchers("/login.html").permitAll()//该路径不需要身份认证

.antMatchers("/authentication/require").permitAll()

.antMatchers("/code/image").permitAll()

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

@Beanpublic PersistentTokenRepository persistentTokenRepository() {

JdbcTokenRepositoryImpl tokenRepository=new JdbcTokenRepositoryImpl();

tokenRepository.setDataSource(dataSource);

tokenRepository.setCreateTableOnStartup(true);//第一次运行开启,创建数据库的表,以后不需要,注释掉

returntokenRepository;

}

}

2、测试

1)启动项目,数据库SpringSecurity中默认创建persistent_logins表,结构如下:

debad2f3493ba11fec0eb277a0a10e62.png

2)访问http://localhost:8080/index.html,用账号user登录,persistent_logins表中存了user账号的信息

32de7e3fe8d95ac0f213ca42daf43cdf.png

3)重启项目,再次访问http://localhost:8080/index.html,无需登录直接进入index.html页面

4)验证记住我时间

4.1)设置为1分钟,清空表persistent_logins,启动项目,浏览器输入http://localhost:8080/index.html,勾选记住我,登录。停止项目。

4.2)一分钟后,启动项目,输入http://localhost:8080/index.html,发现需要登录,验证生效。勾选记住我,登录。

4.3)查询persistent_logins,发现里面有两条user信息,分别是两次登录时保存的,如下:

021bad94ad570db18d30e1c19c9503db.png

七、Session管理

1、设置超时时间

application.properties,新增以下配置,Session配置为1分钟(SpringBoot中最小一分钟)

server.servlet.session.timeout=1m

2、设置超时后跳转地址

1)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.sessionManagement()

.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

... ...

}

}

2)SecurityController.java

@RestControllerpublic classSecurityController {

... ...

@GetMapping("/session/invalid")

@ResponseStatus(code=HttpStatus.UNAUTHORIZED)publicSimpleResponse sessionInvalid() {

System.out.println("session失效");return new SimpleResponse("session失效");

}

}

测试:启动项目,访问localhost:8080/index.html,登陆,停止项目后再次启动,刷新该地址,浏览器出现“session失效”。

3、设置单机登陆

WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.sessionManagement()

.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

.maximumSessions(1);//最大session数量,1代表只能一个登录,后面的会把前面的踢掉

... ...

}

}

测试:Chrome浏览器访问localhost:8080/index.html,用sl登陆;换360浏览器访问该地址,再次用sl登陆,刷新Chrome,如下:

aa370385118515f47296b856e3103188.png

4、Session达到最大数后,阻止后面的登录

WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

http.sessionManagement()

.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

.maximumSessions(1)//最大session数量,1代表只能一个登录,后面的会把前面的踢掉

.maxSessionsPreventsLogin(true);//session数量达到了后,阻止后面的登录... ...

}}

测试:用两个浏览器先后登录,第二个登录后页面显示:{"content":"访问的服务需要身份认证,请引导用户到登录页"}

5、Session被踢掉后的处理

1)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.sessionManagement()

.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

.maximumSessions(1)//最大session数量,1代表只能一个登录,后面的会把前面的踢掉//.maxSessionsPreventsLogin(true)//session数量达到了后,阻止后面的登录

.expiredSessionStrategy(new MyexpiredSessionStrategy());//踢掉先登录的session,先登录的再请求后端进入该类的方法... ...

}

}

2)MyexpiredSessionStrategy.java

public class MyexpiredSessionStrategy implementsSessionInformationExpiredStrategy{

@Overridepublic void onExpiredSessionDetected(SessionInformationExpiredEvent event) throwsIOException, ServletException {

event.getResponse().setContentType("application/json;charset=UTF-8");

event.getResponse().getWriter().write("并发登录");

}

}

测试 :先用Chrome浏览器登录,在用360登录,然后刷新Chrome,页面出现“并发登录” 。

说明:不能与maxSessionsPreventsLogin同时设置,否则不会生效,会执行阻止后面的登录的逻辑。

八、退出操作

1、默认退出操作

1)执行退出操作做的事:使当前Session失效;清除与当前用户相关的remember-me记录;清除当前的SecurityContext;重定向到登录页。

2)添加退出的超级链接:退出,点击就能退出。

2、自定义退出连接

1)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.logout().logoutUrl("/signOut")//指定退出的连接,默认/logout

... ...

}

}

2)添加退出的超级链接:退出,点击就能退出。

3、自定义退出后跳转的url

WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.sessionManagement()//.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

.maximumSessions(1)//最大session数量,1代表只能一个登录,后面的会把前面的踢掉//.maxSessionsPreventsLogin(true)//session数量达到了后,阻止后面的登录

.expiredSessionStrategy(new MyexpiredSessionStrategy());//踢掉先登录的session,先登录的再请求后端进入该类的方法

http.logout()

.logoutUrl("/signOut")//指定退出的连接,默认/logout

.logoutSuccessUrl("/logout.html");//自动退出后跳转的url,默认跳到登录的url上http.authorizeRequests()

.antMatchers("/login.html","/authentication/require","/code/image","/session/invalid","/logout.html").permitAll()//该路径不需要身份认证

.anyRequest()

.authenticated();

http.csrf().disable();//先禁止掉跨站请求伪造防护功能

}

}

说明:必须去掉 invalidSessionUrl 配置项,否则点击退出后,会跳转到 invalidSessionUrl指定的连接。

4、自定义退出后跳转处理

1)WebSecurityConfig.java

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter{

... ...

@AutowiredprivateMyLogoutSuccessHandler logoutSuccessHandler;

@Overrideprotected void configure(HttpSecurity http) throwsException {

... ...

http.sessionManagement()

.invalidSessionUrl("/session/invalid")//session超时后的跳转地址,不会进入loginPage定义的地址中了

.maximumSessions(1)//最大session数量,1代表只能一个登录,后面的会把前面的踢掉//.maxSessionsPreventsLogin(true)//session数量达到了后,阻止后面的登录

.expiredSessionStrategy(new MyexpiredSessionStrategy());//踢掉先登录的session,先登录的再请求后端进入该类的方法

http.logout()

.logoutUrl("/signOut")//指定退出的连接,默认/logout//.logoutSuccessUrl("/logout.html")//自动退出后跳转的url,默认跳到登录的url上

.logoutSuccessHandler(logoutSuccessHandler)//退出成功后,自定义的操作,不能与logoutSuccessUrl同时存在

.deleteCookies("JSESSIONID");

... ...

}

}

2)MyLogoutSuccessHandler.java

@Componentpublic class MyLogoutSuccessHandler implementsLogoutSuccessHandler {

@AutowiredprivateSecurityProperties securityProperties;private ObjectMapper objectMapper=newObjectMapper();

@Overridepublic voidonLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throwsIOException, ServletException {

System.out.println("onLogoutSuccess:退出成功!");

LoginResponseType loginType=securityProperties.getLoginType();if(LoginResponseType.JSON.equals(loginType)) {

response.setContentType("application/json;charset=UTF-8");

response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse("退出成功!")));

}else{

response.sendRedirect("/logout.html");

}

}

}

project.security.loginType配置为REDIRECT,退出后跳转到 logout.html页面;配置为JSON,页面显示出:{"content":"退出成功!"}。

logoutSuccessHandler与logoutSuccessUrl同时配置,logoutSuccessUrl会失效。

优先级:logoutSuccessHandler > invalidSessionUrl > logoutSuccessUrl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值