spring security 默认情况下登录成功会跳转到引发登录的请求上去,但是有些登录并不是同步访问的,而是ajax异步请求来访问登录,那么前端希望拿到的是登录用户的用户信息。
在/src/main/resources
的resources目录新建index.html:
<html>
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
index<br>
body>
html>
新建登录成功跳转方式枚举:
package com.xh.sercurity.properties;
public enum LoginType {
REDIRECT,// 跳转
JSON// 返回json
}
新建处理自定义配置的类,并把LoginType加入进去:
package com.xh.sercurity.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "xh.security")
public class SecurityProperties {
private LoginType loginType = LoginType.JSON; // default json
public LoginType getLoginType() {
return loginType;
}
public void setLoginType(LoginType loginType) {
this.loginType = loginType;
}
}
那么就可以在application.properties中定义不同类型的返回方式。
使前面的configration配置类生效:
package com.xh.sercurity.config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import com.xh.sercurity.properties.SecurityProperties;
@Configuration
@EnableConfigurationProperties(SecurityProperties.class)// 使SecurityProperties生效
public class SecurityPropertiesConfig {
}
package com.xh.sercurity.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.xh.sercurity.properties.LoginType;
import com.xh.sercurity.properties.SecurityProperties;
/**
* 登录成功的处理器
*/
@Component("myAuthenticationSuccessHandler")
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SecurityProperties myProperties;
// Authentication 封装认证信息
// 登录方式不同,Authentication不同
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
logger.info("MyAuthenticationSuccessHandler login success!");
if (LoginType.JSON.equals(myProperties.getLoginType())) {
response.setContentType("application/json;charset=UTF-8");
// 把authentication对象转成 json 格式 字符串 通过 response 以application/json;charset=UTF-8 格式写到响应里面去
response.getWriter().write(objectMapper.writeValueAsString(authentication));
} else {
// 父类的方法 就是 跳转
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
package com.xh.sercurity.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.xh.sercurity.properties.LoginType;
import com.xh.sercurity.properties.SecurityProperties;
import com.xh.sercurity.support.SimpleResponse;
/**
* 登录失败的处理器
*/
@Component("myAuthenctiationFailureHandler")
public class MyAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SecurityProperties securityProperties;
// AuthenticationException 认证过程中产生的异常
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
logger.info("MyAuthenticationSuccessHandler login failure!");
if (LoginType.JSON.equals(securityProperties.getLoginType())) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.setContentType("application/json;charset=UTF-8");
// response.getWriter().write(objectMapper.writeValueAsString(exception));
response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage())));
} else {
super.onAuthenticationFailure(request, response, exception);
}
}
}
package com.xh.sercurity.config;
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 org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder () {
return new BCryptPasswordEncoder();
}
@Autowired
private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler myAuthenctiationFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.httpBasic()// httpBasic 登录
http.formLogin()// 表单登录 来身份认证
.loginPage("/authentication/require")// 自定义登录页面
.loginProcessingUrl("/authentication/form")// 自定义登录路径
.successHandler(myAuthenticationSuccessHandler)
.failureHandler(myAuthenctiationFailureHandler)
.and()
.authorizeRequests()// 对请求授权
// error 127.0.0.1 将您重定向的次数过多
.antMatchers("/myLogin.html", "/authentication/require",
"/authentication/form").permitAll()// 这些页面不需要身份认证,其他请求需要认证
.anyRequest() // 任何请求
.authenticated()//; // 都需要身份认证
.and()
.csrf().disable();// 禁用跨站攻击
}
}