Spring Security 自定义登录成功和登录失败的处理

一、前言

spring security 默认情况下登录成功会跳转到引发登录的请求上去,但是有些登录并不是同步访问的,而是ajax异步请求来访问登录,那么前端希望拿到的是登录用户的用户信息。

二、自定义登录成功和登录失败的返回方式

/src/main/resources的resources目录新建index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</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);
        }
    }

}

五、把自定义处理器加入security认证中

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();// 禁用跨站攻击
    }

}
  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Security提供了很多自定义登录的方式,以下是一种常见的自定义登录流程: 1. 创建一个实现了UserDetailsService接口的自定义UserDetailsService类,用于从数据库或其他数据源中获取用户信息。该接口有一个loadUserByUsername方法,根据用户名加载用户信息并返回一个UserDetails对象。 2. 创建一个实现了PasswordEncoder接口的密码编码器类,用于对用户密码进行加密和验证。常见的实现类有BCryptPasswordEncoder和PasswordEncoder,可以根据项目需求选择合适的实现类。 3. 创建一个继承自WebSecurityConfigurerAdapter的配置类,并重写configure方法。在该方法中,可以配置登录页面、登录成功后的跳转页面、登录失败后的处理等。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/css/**", "/js/**", "/images/**").permitAll() // 静态资源放行 .antMatchers("/login").permitAll() // 登录页面放行 .anyRequest().authenticated() // 其他请求需要认证 .and() .formLogin() .loginPage("/login") // 自定义登录页面路径 .defaultSuccessUrl("/home") // 登录成功后的默认跳转路径 .failureUrl("/login?error") // 登录失败后的路径 .and() .logout() .logoutUrl("/logout") // 退出登录的路径 .logoutSuccessUrl("/login?logout") // 退出登录后的路径 .and() .csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); } } ``` 4. 在登录页面的表单中,需要包含用户名和密码的输入框,并将表单提交到Spring Security提供的默认登录处理路径("/login")。 这样就完成了一个简单的Spring Security自定义登录流程。你可以根据项目需求进行更多的自定义配置,例如添加记住我功能、验证码等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值