SpringSecurity(02)

自定义登录页面

http.formLogin()

  1. loginPage(String loginPage):设置用户登录页面的访问路径,默认为 GET 请求的 /login。
  2. loginProcessingUrl(String loginProcessingUrl):设置登录表单提交的路径,默认为是 POST 请求的 loginPage() 设置的路径
  3. successForwardUrl(String forwordUrl):设置用户认证成功后转发的地址。
  4. successHandler(AuthenticationSuccessHandler successHandler):配置用户认证成功后的自定义处理器。
  5. defaultSuccessUrl(String defaultSuccessUrl):设置用户认证成功后重定向的地址。这里需要注意,该路径是用户直接访问登录页面认证成功后重定向的路径,如果是其他路径跳转到登录页面认证成功后会重定向到原始访问路径。可设置第二个参数为 true,使认证成功后始终重定向到该地址。
  6. failureForwrad(String forwardUrl):设置用户认证失败后转发的地址。
  7. failureHandler(AuthenticationFailureHandler authenticationFailureHandler):设置用户登录失败后的自定义错误处理器。
  8. failureUrl(String authenticationFailureUrl):设置用户登录失败后重定向的地址,指定的路径要能匿名访问,默认为loginPage() + ?error。
  9. usernameParamter(String usernameParamter):设置登录表单中的用户名参数,默认为 username。
  10. passwordParamter(String passwordParamter):设置登录表单中的密码参数,默认为 password。
DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>登录title>
head>
<body>
<form class="login-page" action="/login" method="post">
    <div class="form">
        <h3>账户登录h3>
        <input type="text" placeholder="用户名" name="username" required="required" />
        <input type="password" placeholder="密码" name="password" required="required" />
        <button type="submit">登录button>
    div>
form>
body>
html>
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * fromLogin():表单认证
         * httpBasic():弹出框认证
         * authorizeRequests():身份认证请求
         * anyRequest():所有请求
         * authenticated():身份认证
         * loginPage():登录页面地址
         * loginProcessingUrl():登录表单提交地址
         * csrf().disable():关闭Spring Security的跨站请求伪造的功能
         */
        http.csrf().disable()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                .antMatchers("/login.html").permitAll()
                .anyRequest()
                .authenticated();
    }
}

注意:SpringBoot项目集成Spring Security 5.3.4RELEASE后,默认情况crsf是开启的。每次请求会校验请求头中 X-CSRF-TOKEN 的值与内存中保存的是否一致,如果一致框架则认为登录页面是安全的,如果不一致,会报403。

@Controller
public class LoginController {
    
    @RequestMapping("/login.html")
    public String login(){
        return "login";
    }
    
    @RequestMapping("/test")
    @ResponseBody
    public String test(){
        return "test";
    }
}

SpringSecurity(02)_第1张图片

  1. 转发
http.formLogin()
    .usernameParameter("name") // 设置请求参数中,用户名参数名称。 默认username
    .passwordParameter("pswd") // 设置请求参数中,密码参数名称。 默认password
    .loginPage("/toLogin") // 当用户未登录的时候,跳转的登录页面地址是什么? 默认 /login
    .loginProcessingUrl("/login") // 用户登录逻辑请求地址是什么。 默认是 /login
    .failureForwardUrl("/failure"); // 登录失败后,请求转发的位置。Security请求转发使用Post请求。默认转发到:loginPage?error
    .successForwardUrl("/toMain"); // 用户登录成功后,请求转发到的位置。Security请求转发使用POST请求。
  1. 重定向
http.formLogin()
    .usernameParameter("name") // 设置请求参数中,用户名参数名称。 默认username
    .passwordParameter("pswd") // 设置请求参数中,密码参数名称。 默认password
    .loginPage("/toLogin") // 当用户未登录的时候,跳转的登录页面地址是什么? 默认 /login
    .loginProcessingUrl("/login") // 用户登录逻辑请求地址是什么。 默认是 /login
 	.defaultSuccessUrl("/toMain",true); //用户登录成功后,响应重定向到的位置。GET请求。必须配置绝对地址。
  	.failureUrl("/failure"); // 登录失败后,重定向的位置。

自定义登录处理器

  1. AuthenticationSuccessHandler:用来处理认证成功的情况
  2. AuthenticationFailureHandler:用来处理认证失败的情况
@Slf4j
@Component
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        log.info("登录成功");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(authentication));
    }
}
@Slf4j
@Component
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.info("登录失败");
        httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(e));
    }
}
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /*@Resource
    private PasswordEncoder passwordEncoder;
	@Resource
    private UserDetailsService userDetailsService;*/
    @Autowired
    private AuthenticationSuccessHandlerImpl authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandlerImpl authenticationFailureHandler;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * fromLogin():表单认证
         * httpBasic():弹出框认证
         * authorizeRequests():身份认证请求
         * anyRequest():所有请求
         * authenticated():身份认证
         * loginPage():登录页面地址
         * loginProcessingUrl():登录表单提交地址
         * csrf().disable():关闭Spring Security的跨站请求伪造的功能
         */
        http.csrf().disable()
        		.formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/auth/login")
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .and()
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest()
                .authenticated();
    }
    
    /**
    * 认证管理器:
    * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
    * 2、可采用内存存储方式,也可能采用数据库方式等
    */
    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 不再使用内存方式存储用户认证信息,而是动态从数据库中获取
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }*/
}

自定义退出处理器

Spring Security默认的退出登录URL为/logout,退出登录后,Spring Security会做如下处理:

  1. 使当前的Session失效
  2. 清除与当前用户关联的RememberMe记录
  3. 清空当前的SecurityContext
  4. 重定向到登录页

通过退出成功处理器来实现

@GetMapping("/signout/success")
public String signout() {
    return "退出成功,请重新登录";
}
@Component
public class MyLogOutSuccessHandler implements LogoutSuccessHandler {
    
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write("退出成功,请重新登录");
    }
}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /*@Resource
    private PasswordEncoder passwordEncoder;
	@Resource
    private UserDetailsService userDetailsService;*/
    @Autowired
    private AuthenticationSuccessHandlerImpl authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandlerImpl authenticationFailureHandler;
    @Resource
	private MyLogOutSuccessHandler logOutSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .and()
                .logout()
                //.logoutUrl("/signout")
                .logoutSuccessUrl("/signout/success")
        		.deleteCookies("JSESSIONID")
                .logoutSuccessHandler(logoutSuccessHandler)
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();
    }
    
    /**
    * 认证管理器:
    * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
    * 2、可采用内存存储方式,也可能采用数据库方式等
    */
    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 不再使用内存方式存储用户认证信息,而是动态从数据库中获取
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }*/
}

你可能感兴趣的:(SpringSecurity,java,spring)