Spring security自定义用户认证流程详解

网友投稿 483 2022-12-12


Spring security自定义用户认证流程详解

1.自定义登录页面

(1)首先在static目录下面创建login.html

注意:springboot项目默认可以访问resources/resources,resources/staic,resources/public目录下面的静态文件

用户名:


密 码:


(2)在spring securiy配置类中做如下配置

@Override

protected void configure(HttpSecurity http) throws Exception {

http.formLogin()

// 指定自定义登录页面

.loginPage("/login.html")

// 登录url

.loginProcessingUrl("/auth/login")

.and()

.authorizeRequests()

// 添加一个url匹配器,如果匹配到login.html,就授权

.antMatchers("/login.html").permitAll()

.anyRequest()

.authenticated()

.and()

// 关闭spring security默认的防csrf攻击

.csrf().disable();

}

(3)测试

(4)存在的问题

<1>作为可以复用的登录模块,我们应该提供个性化的登录页面,也就是说不能写死只跳转到login.html。

此问题比较好解决,使用可配置的登录页面,默认使用login.html即可。

<2> 请求跳转到login.html登录页面,貌似没有什么问题,但作为restful风格的接口,一般响应的都是json数据格式,尤其是appVLDtFWMY请求。

解决思想:用户发起数据请求 --> security判断是否需要身份认证 ----->跳转到一个自定义的controller方法 ------>在该方法内判断是否是html发起的请求,如果是,就跳转到login.html,如果不是,响应一个json格式的数据,说明错误信息。

自定义Controller

@Slf4j

@RestController

public class LoginController {

/**

* 请求缓存

*/

private RequestCache requestCache = new HttpSessionRequestCache();

/**

* 重定向工具类

*/

private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

/**

* 如果配置的登录页就使用配置的登录面,否则使用默认的登录页面

*/

// @Value("${xxxx:defaultLoginPage}")

// private String standardLoginPage;

private String standardLoginPage = "/login.html"; // 登录页

/**

* 用户身份认证方法

*/

@GetMapping("/user/auth")

@ResponseStatus(code = HttpStatus.UNAUTHORIZED) // 返回状态

public ResponseData login(HttpServletRequest request, HttpServletResponse response) throws IOException {

SavedRequest savedRequest = requestCache.getRequest(request, response);

if (savedRequest != null) {

String targetUrl = savedRequest.getRedirectUrl();

log.info("请求是:" + targetUrl);

// 如果请求是以html结尾

if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {

redirectStrategy.sendRedirect(request, response, standardLoginPage);

}

}

return new ResponseData("该请求需要登录,js拿到我的响应数据后,是否需要跳转到登录页面你自己看着办吧?");

}

}

spring security给该controller的login方法授权

@Override

protected void configure(HttpSecurity http) throws Exception {

http.formLogin()

// 先进controller中去

.loginPage("/user/auth")

// 指定自定义登录页面

.loginPage("/login.html")

// 登录url

.loginProcessingUrl("/auth/login")

.and()

.authorizeRequests()

// 该controller需要授权

.antMatchers("/user/auth").permitAll()

// 添加一个url匹配器,如果匹配到login.html,就授权

.antMatchers("/login.html").permitAll()

.anyRequest()

.authenticated()

.and()

// 关闭spring security默认的防csrf攻击

.csrf().disable();

}

这样子就行了!!!

2. 自定义登录成功处理(返回json)VLDtFWMY

(1)实现AuthenticationSuccessHandler.java

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.MediaType;

import org.springframework.security.core.Authentication;

import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import org.springframework.stereotype.Component;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@Slf4j

@Component

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

@Autowired

private ObjectMapper objectMapper;

/**

* Called when a user has been successfully authenticated.

* @param request

* @param response

* @param authentication

* @throws IOException

* @throws ServletException

*/

@Override

public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

log.info("登录成功!!!");

// 将登录成功的信息写到前端

response.setContentType(MediaType.APPLICATION_JSON_VALUE);

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

}

}

(2)修改security配置类

@Autowired

private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

@Override

protected void configure(HttpSecurity http) throws Exception {

http.formLogin()

// 先进controller中去

.loginPage("/user/auth")

// 指定自定义登录页面

.loginPage("/login.html")

// 登录VLDtFWMYurl

.loginProcessingUrl("/auth/login")

.successHandler(myAuthenticationSuccessHandler)

.and()

.authorizeRequests()

// 该controller需要授权

.antMatchers("/user/auth").permitAll()

// 添加一个url匹配器,如果匹配到login.html,就授权

.antMatchers("/login.html").permitAll()

.anyRequest()

.authenticated()

.and()

// 关闭spring security默认的防csrf攻击

.csrf().disable();

}

(3)测试

说明:authentication对象中包含的信息,会因为登录方式的不同而发生改变

3.自定义登录失败处理(返回json)

实现AuthenticationFailureHandler.java接口即可,跟登录成败处理配置一样。

4.自定义登录成功处理逻辑

以上的登录成功或失败的返回的都是json,但是在某些情况下,就是存在着登录成功或者失败进行页面跳转(spring security默认的处理方式),那么这种返回json的方式就不合适了。所以,我们应该做得更灵活,做成可配置的。

对于登录成功逻辑而言只需要对MyAuthenticationSuccessHandler.java稍做修改就行,代码如下所示:

/**

* SavedRequestAwareAuthenticationSuccessHandler spring security 默认的成功处理器

*/

@Slf4j

@Component

public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

@Autowired

private ObjectMapper objectMapper;

/**

* 配置的登录方式

*/

// @Value("${xxx:默认方式}")

private String loginType = "JSON";

/**

* Called when a user has been successfully authenticated.

*/

@Override

public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

log.info("登录成功!!!");

// 如果配置的登录方式是JSON,就返回json数据

if ("JSON".equals(loginType)) {

// 将登录成功的信息写到前端

response.setContentType(MediaType.APPLICATION_JSON_VALUE);

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

} else { // 否则就使用默认的跳转方式

super.onAuthenticationSuccess(request,response,authentication);

}

}

}

5.自定义登录失败处理逻辑

同登录成功类似,具体代码如下:

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpStatus;

import org.springframework.http.MediaType;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

import org.springframework.stereotype.Component;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@Slf4j

@Component

public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

@Autowired

private ObjectMapper objectMapper;

/**

* 配置的登录方式

*/

// @Value("${xxx:默认方式}")

private String loginType = "JSON";

@Override

public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

log.info("登录失败!!!");

// 如果配置的登录方式是JSON,就返回json数据

if ("JSON".equals(loginType)) {

// 将登录成功的信息写到前端

response.setStatus(HttpStatus.UNAUTHORIZED.value());

response.setContentType(MediaType.APPLICATION_JSON_VALUE);

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

} else { // 否则就使用默认的跳转方式,跳转到一个错误页面

super.onAuthenticationFailure(request,response,exception);

}

}

}

@Autowired

private MySimpleUrlAuthenticationFailureHandler mySimpleUrlAuthenticationFailureHandler;

@Override

protected void configure(HttpSecurity http) throws Exception {

http.formLogin()

// 先进controller中去

.loginPage("/user/auth")

// 指定自定义登录页面

.loginPage("/login.html")

// 登录url

.loginProcessingUrl("/auth/login")

.successHandler(myAuthenticationSuccessHandler)

.failureHandler(mySimpleUrlAuthenticationFailureHandler)

.and()

.authorizeRequests()

// 该controller需要授权

.antMatchers("/user/auth").permitAll()

// 添加一个url匹配器,如果匹配到login.html,就授权

.antMatchers("/login.html").permitAll()

.anyRequest()

.authenticated()

.and()

// 关闭spring security默认的防csrf攻击

.csrf().disable();

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Android Studio无法执行Java类的main方法问题及解决方法
下一篇:java.lang.Runtime.exec() Payload知识点详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~