0
点赞
收藏
分享

微信扫一扫

3-SpringSecurity:自定义Form表单

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

// There is no PasswordEncoder mapped for the id "null"

PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

String yourPassword = "123";

System.out.println("Encoded password: " + encoder.encode(yourPassword));

// Config account info and permissions

auth.inMemoryAuthentication()

.withUser("dev").password(encoder.encode(yourPassword)).authorities("p1")

.and()

.withUser("test").password(encoder.encode(yourPassword)).authorities("p2");

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.httpBasic();

}

在这里插入图片描述

[]( )实验1:自定义登录页面

  • 登录页面配置

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.csrf().disable() // turn off csrf, or will be 403 forbidden

.formLogin() // Support form and HTTPBasic

.loginPage("/login");

}

  • 后端登录页面接口

@Controller

public class LoginController {

@GetMapping("/login")

public String login() {

return "login";

}

@GetMapping(value = "/user/add")

@ResponseBody

public String accessResource1() {

return " Access Resource 1: Add User";

}

@GetMapping(value = "/user/query")

@ResponseBody

public String accessResource2() {

return " Access Resource 2: Query User";

}

}

  • 前端模板

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Login</title>

</head>

<body>

<form action="login" method="post">

<span>用户名</span><input type="text" name="username" /> <br>

<span>密码</span><input type="password" name="password" /> <br>

<input type="submit" value="登录">

</form>

</body>

</html>

Note:此时,需要先关闭CSRF,.csrf().disable(),否则报403;

[]( )实验2:自定义登录接口

默认登录页面接口与登录数据提交接口是同一个:/login,顺着.loginPage,进入FormLoginConfigurer,源码如下:

@Override

public FormLoginConfigurer<H> loginPage(String loginPage) {

return super.loginPage(loginPage);

}

继续进入父类的loginPage方法,

protected T loginPage(String loginPage) {

setLoginPage(loginPage);

updateAuthenticationDefaults();

this.customLoginPage = true;

return getSelf();

}

继续跟踪进入方法updateAuthenticationDefaults();,可以看到,如果没有配置loginProcessingUrl,那么loginProcessingUrlloginPage便相同。

protected final void updateAuthenticationDefaults() {

if (loginProcessingUrl == null) {

loginProcessingUrl(loginPage);

}

if (failureHandler == null) {

failureUrl(loginPage + "?error");

}

final LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(

LogoutConfigurer.class);

if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {

logoutConfigurer.logoutSuccessUrl(loginPage + "?logout");

}

}

下面我们自定义登录数据提交接口为/formLogin,此时相应的前端action也要修改。

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.csrf().disable() // turn off csrf, or will be 403 forbidden

.formLogin() // Support form and HTTPBasic

.loginPage("/login")

.loginProcessingUrl("/formLogin");

}

<form action="formLogin" method="post">

<span>用户名</span><input type="text" name="username" /> <br>

<span>密码</span><input type="password" name="password" /> <br>

<input type="submit" value="登录">

</form>

[]( )实验3:自定义登录数据参数

  • 前面我们自定义了登录页面,在form表单中设置用户名、密码分别为username, password,那为什么这样写呢,可以改成别的嘛?可以倒是可以,但是不能随便改;

  • 如果这里我们把username改为name,再次尝试登录,后端接口将报错:org.springframework.security.authentication.BadCredentialsException: Bad credentials。。可是实际项目中我们的用户名密码就是不叫这个名字呢?我们可以进行配置.usernameParameter("name")

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.csrf().disable() // turn off csrf, or will be 403 forbidden

.formLogin() // Support form and HTTPBasic

.loginPage("/login")

.loginProcessingUrl("/formLogin")

.usernameParameter("name");

}

<form action="formLogin" method="post">

<span>用户名</span><input type="text" name="name" /> <br>

<span>密码</span><input type="password" name="password" /> <br>

<input type="submit" value="登录">

</form>

默认的用户名、密码分别为username, password,我们看下SpringSecurity的源码:

public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends

AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {

/**

  • Creates a new instance

  • @see HttpSecurity#formLogin()

*/

public FormLoginConfigurer() {

super(new UsernamePasswordAuthenticationFilter(), null);

usernameParameter("username");

passwordParameter("password");

}

}

[]( )实验4:自定义登录失败、成功处理器

问题:就以上个实验3中的报错信息为例,或当用户名、密码输错后,如何在后台看到错误信息?

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.csrf().disable() // turn off csrf, or will be 403 forbidden

.formLogin() // Support form and HTTPBasic

.loginPage("/login")

.loginProcessingUrl(

3-SpringSecurity:自定义Form表单

"/formLogin")

.usernameParameter("name")

.failureHandler(new AuthenticationFailureHandler(){

@Override

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

exception.printStackTrace();

request.getRequestDispatcher(request.getRequestURL().toString()).forward(request, response);

}

});

}

常见的认证异常,这里可以看到AuthenticationException共有18个子类:

在这里插入图片描述

上述增加了在认证失败时的处理:输出错误信息。同理,如果想在登录成功时直接进行一些处理(eg: 数据初始化等),可以使用以下配置:

.successHandler(new AuthenticationSuccessHandler() {

@Override

public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,

Authentication authentication) throws IOException, ServletException {

System.out.println("Login Successfully~");

// do something here: initial work or forward to different url regarding different roles

...

request.getRequestDispatcher("").forward(request, response);

}

})

[]( )实验5:自定义登录成功跳转页面

经历千难万险,终于要登录成功了。进来之后要跳转到哪里呢?看你喽~想跳哪里跳哪里。。

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

.antMatchers("/user/add").hasAuthority("p1")

.antMatchers("/user/query").hasAuthority("p2")

.antMatchers("/user/**").authenticated()

.anyRequest().permitAll() // Let other request pass

.and()

.csrf().disable() // turn off csrf, or will be 403 forbidden

.formLogin() // Support form and HTTPBasic

.loginPage("/login")

.loginProcessingUrl("/formLogin")

.usernameParameter("name")

.failureHandler(new AuthenticationFailureHandler(){

@Override

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

exception.printStackTrace();

request.getRequestDispatcher(request.getRequestURL().toString()).forward(request, response);

}

})

.successForwardUrl("/ok"); // custom login success page, a POST request

}

@Controller

public class LoginController {

...

@PostMapping(value = "/ok")

@ResponseBody

public String ok() {

return "ok";

}

}

举报

相关推荐

0 条评论