Spring Security(六):自定义登录成功与失败处理

基本思路:实现AuthenticationSuccessHandler或AuthenticationFailureHandler接口,并进行相应的配置就可以了。当然框架有默认的实现类,也可以继承实现类再来自定义自己的业务。
 

操作流程


1、【zjj-security-demo 工程】修改application.yml

屏蔽属性loginPage,为后面一会测试使用,新增属性loginType 用于登录成功返回的是跳转页面还是返回JSON使用

spring: 
  datasource: 
    driver-class-name: com.mysql.jdbc.Driver 
    url: jdbc:mysql://127.0.0.1:3306/xxx?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: 用户名
    password: 密码
  # session会话  先关闭
  session: 
    store-type: none

# 身份开启 spring security 当值为true 则需要进行认证登录操作
security:
  basic:
    enabled: true

# 配置html请求指定认证跳转页面
zjj:  
  security: 
    browser: 
# 屏蔽属性loginPage,新增属性loginType 用于登录成功返回的是跳转页面还是返回JSON使用
#     loginPage: /demo-sign.html
      loginType: REDIRECT

 

2、【zjj-security-core工程】BrowserProperties配置类,新增对应属性

package com.zjj.security.core.properties;

public class BrowserProperties {

	// loginPage = "/zjj-login.html":当zjj-security-demo 不配置 zjj.security.browser.loginPage 时默认跳转的页面
	private String loginPage = "/zjj-login.html";
	
	// 设置默认返回的类型
	private LoginResponseType loginType = LoginResponseType.JSON;

	public String getLoginPage() {
		return loginPage;
	}
	public void setLoginPage(String loginPage) {
		this.loginPage = loginPage;
	}

	public LoginResponseType getLoginType() {
		return loginType;
	}
	public void setLoginType(LoginResponseType loginType) {
		this.loginType = loginType;
	}
}

 

3、【zjj-security-core工程】新增枚举类,用于设置登录返回的类型

package com.zjj.security.core.properties;
public enum LoginResponseType {
	
	/**
	 * 跳转
	 */
	REDIRECT,
	
	/**
	 * 返回json
	 */
	JSON
} 

 

 

登录成功处理


1、【zjj-security-broswer工程】新增类,实现AuthenticationSuccessHandler接口或继承相关实现类

根据需要返回的不同类型,做出处理

package com.zjj.security.browser.authentication;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjj.security.core.properties.LoginResponseType;
import com.zjj.security.core.properties.SecurityProperties;

@Component("zjjAuthenticationSuccessHandler")
public class ZjjAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ObjectMapper objectMapper;
	
	@Autowired
	private SecurityProperties securityProperties;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		logger.info("登录成功");
		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(authentication));
		} else {
			super.onAuthenticationSuccess(request, response, authentication);
		}
	}
}

2、【zjj-security-broswer工程】config 类定义用户登录成功的处理

package com.zjj.security.browser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.zjj.security.browser.authentication.ZjjAuthenticationFailureHandler;
import com.zjj.security.browser.authentication.ZjjAuthenticationSuccessHandler;
import com.zjj.security.core.properties.SecurityProperties;

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private SecurityProperties securityProperties;
	
	@Autowired
	private ZjjAuthenticationSuccessHandler zjjAuthenticationSuccessHandler;

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.formLogin() // 定义是否使用表单登录
		.loginPage("/authentication/require") 
		.loginProcessingUrl("/authentication/form") // 自定义登录接口
		.successHandler(zjjAuthenticationSuccessHandler) // 定义用户登录成功的处理
		.and()
		.authorizeRequests() // 对所有请求进行授权
		.antMatchers("/authentication/require", securityProperties.getBrowser().getLoginPage()).permitAll()
		.anyRequest()	 // 任何请求
		.authenticated() // 都需要身份认证
		.and()
        .csrf().disable(); // 关闭csrf防护
	}
}

3、【zjj-security-demo 工程】在\src\main\resources下新建文件夹resources,并创建index.html页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
	index
</body>
</html>

4、【 zjj-security-demo工程 】启动ZjjSecurityDemoApplication 类main方法

a、设置zjj-security-demo工程application.yml中的zjj.security.browser.loginType=REDIRECT 并访问 http://localhost:8080/index.html,登录成功后返回到 http://localhost:8080/index.html 并打印

index

b、设置zjj-security-demo工程application.yml中的zjj.security.browser.loginType=JSON  并访问 http://localhost:8080/index.html,登录成功后页面打印

{
	"authorities": [{
		"authority": "admin"
	}],
	"details": {
		"remoteAddress": "0:0:0:0:0:0:0:1",
		"sessionId": "CFC97202A3E9F18084DD5C1E977CF0DA"
	},
	"authenticated": true,
	"principal": {
		"password": null,
		"username": "zjj",
		"authorities": [{
			"authority": "admin"
		}],
		"accountNonExpired": true,
		"accountNonLocked": true,
		"credentialsNonExpired": true,
		"enabled": true
	},
	"credentials": null,
	"name": "zjj"
}

 

 

登录失败处理


1、【zjj-security-broswer工程】新增类,实现AuthenticationSuccessHandler接口或继承相关实现类

根据需要返回的不同类型,做出处理

package com.zjj.security.browser.authentication;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjj.security.core.properties.LoginResponseType;
import com.zjj.security.core.properties.SecurityProperties;

@Component("zjjAuthenticationFailureHandler")
public class ZjjAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ObjectMapper objectMapper;
	
	@Autowired
	private SecurityProperties securityProperties;

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		logger.info("登录失败");
		
		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {
			// 设置返回的状态码
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(exception.getMessage()));
		} else {
			super.onAuthenticationFailure(request, response, exception);
		}
	}
}

2、【zjj-security-broswer工程】config 类定义用户登录失败的处理

package com.zjj.security.browser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.zjj.security.browser.authentication.ZjjAuthenticationFailureHandler;
import com.zjj.security.browser.authentication.ZjjAuthenticationSuccessHandler;
import com.zjj.security.core.properties.SecurityProperties;

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private SecurityProperties securityProperties;
	
	@Autowired
	private ZjjAuthenticationSuccessHandler zjjAuthenticationSuccessHandler;

	@Autowired
	private ZjjAuthenticationFailureHandler zjjAuthenticationFailureHandler;

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.formLogin() // 定义是否使用表单登录
		.loginPage("/authentication/require") 
		.loginProcessingUrl("/authentication/form") // 自定义登录接口
		.successHandler(zjjAuthenticationSuccessHandler) // 定义用户登录成功的处理
		.failureHandler(zjjAuthenticationFailureHandler) // 定义用户登录失败的处理
		.and()
		.authorizeRequests() // 对所有请求进行授权
		.antMatchers("/authentication/require", securityProperties.getBrowser().getLoginPage()).permitAll()
		.anyRequest()	 // 任何请求
		.authenticated() // 都需要身份认证
		.and()
        .csrf().disable(); // 关闭csrf防护
	}
}

3、【 zjj-security-demo工程 】启动ZjjSecurityDemoApplication 类main方法

a、设置zjj-security-demo工程application.yml中的zjj.security.browser.loginType=REDIRECT 并访问 http://localhost:8080/index.html,登录失败后返回到 http://localhost:8080/authentication/form 并打印

There was an unexpected error (type=Unauthorized, status=401).
Authentication Failed: 坏的凭证

b、设置zjj-security-demo工程application.yml中的zjj.security.browser.loginType=JSON  并访问 http://localhost:8080/index.html,登录失败后返回到 http://localhost:8080/authentication/form 并打印

"坏的凭证"

源码下载
Spring Security 码云目录一览

更多内容请关注我的个人博客:http://www.zjjfx68.com/ 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值