SpringSecurity授权(二)
SpringBoot+SpringSecurity整合(二)这里写了本章内容需要使用的知识对其不了解的可以看一看,如果是大佬请忽略
SpringSecurity登录成功的控制器编写
如果是前后端分离的项目,一般后端不会储存页面信息,所以不会在同一个端口或者地址上,所以要通过编写成功的控制器,SpringSecurity默认的控制器只能在当前项目下进行页面的跳转不能达到去访问外网的要求
@Override
protected void configure(HttpSecurity http) throws Exception {
// 表单登录
http.formLogin()
// 自定义表单接收参数
.usernameParameter("username")
.passwordParameter("password")
// 设置登录页面
.loginPage("/login.html")
// 登录的请求必须和表单登录的url一致
.loginProcessingUrl("/login")
// 登录成功的页面(这里不能直接写页面要通过POST请求跳到页面)
// .defaultSuccessUrl("/toMain")
// 登录成功的控制器
.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
// 登录失败的页面(这里不能直接写页面要通过POST请求跳到页面)
// .failureForwardUrl("/toError");
// 登录失败的控制器
.failureHandler(new MyAuthenticationFailureHandler("http://www.alibaba.com"));
// 授权
http.authorizeRequests()
// 对登录页面、登录成功的页面,登录失败的请求不做授权访问
.antMatchers("/login.html","/error.html").permitAll()
// 其他所有的请求必须得经过授权,必须登录
.anyRequest().authenticated();
// 关闭CSRF跨域
http.csrf().disable();
}
观察SpringSecurity默认使用的成功之后访问的控制器,使用的是
request.getRequestDispatcher
转发,所以不能达到特定的要求,必须得是重定向,所以我们按照这样的形式创建一个相似的类
public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final String forwardUrl;
/**
* @param forwardUrl
*/
public ForwardAuthenticationSuccessHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> "'" + forwardUrl + "' is not a valid forward URL");
this.forwardUrl = forwardUrl;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}
MyAuthenticationSuccessHandler
编写
从这个
Authentication
类中可以获取到相关用户的一些角色和权限用户名信息,虽然其中有getPassword()
方法但是SpringSecurity为了安全考虑直接将密码设置为了空,所有获取到的密码是null
/**
* 登录成功的handler
*/
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private String url;
public MyAuthenticationSuccessHandler(String url){
this.url=url;
}
/**
*
* @param httpServletRequest
* @param httpServletResponse
* @param authentication 与权限相关的参数,比如可以获取到UserDetails类,再通过其获取到该用户具有哪一些权限
* @throws IOException
* @throws ServletException
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException, ServletException {
User user= (User) authentication.getPrincipal();
System.out.println("user.getAuthorities() = " + user.getAuthorities());
httpServletResponse.sendRedirect(url);
}
}
SpringSecurity登录失败的控制器编写
由上可以知道登录失败也有一个Handler,看源码也是用的
request.getRequestDispatcher
去做转发,同上我们也要编写一个Handler类,和成功的Handler不同的是AuthenticationException
这一个参数他是获取到当前登录失败的原因也就是抛出的异常种类可以如图在其中可以发现UsernameNotFoundException
异常这一个异常是没找到当前用户的异常,在SpringBoot+SpringSecurity整合(二)中可以在loadUserByUsername
中找到
public class ForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final String forwardUrl;
/**
* @param forwardUrl
*/
public ForwardAuthenticationFailureHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> "'" + forwardUrl + "' is not a valid forward URL");
this.forwardUrl = forwardUrl;
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}
MyAuthenticationFailureHandler
编写
/**
* 登录失败的Handler
*/
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
private String url;
public MyAuthenticationFailureHandler(String url){
this.url=url;
}
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.sendRedirect(url);
}
}
启动项目
这样启动项目之后就可以进行登录,登录成功之后就可以访问到外网,注意:url参数必须是全名称