文章目录
- 1、登录成功处理器
- 2、登录失败处理器
- 3、无权限处理器
- 4、登出(退出)处理器
- 5、安全配置类WebSecurityConfig
前后端分离背景下,前后端通过json进行交互,登录成功或失败,返回的不是一个html页面,而是一个json串。
1、登录成功处理器
先定义个统一结果返回类:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class HttpResult {
private Integer code;
private String msg;
private Object data;
public HttpResult(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
定义登录成功处理器,登录成功时,调用它里面的方法:
@Component
public class MyAutheticationSuccessHandle implements AuthenticationSuccessHandler {
@Resource
private ObjectMapper objectMapper; //注入它方便进行对象的序列化和反序列化
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//实体类加了@Builder注解,这里换种方式创建对象
HttpResult httpResult = HttpResult.builder()
.code(200)
.msg("登录成功")
.build();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
String responseJson = objectMapper.writeValueAsString(httpResult);
response.getWriter().write(responseJson);
response.getWriter().flush();
}
}
在Web安全管理适配器这里,改成表单页登录成功后,走登录成功处理器:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
MyAutheticationSuccessHandle myAutheticationSuccessHandle;
@Override
protected void configure(HttpSecurity http) throws Exception {
//任何访问均需要认证
http.authorizeRequests().anyRequest().authenticated();
//登录放行,走登录成功处理器
http.formLogin().successHandler(myAutheticationSuccessHandle).permitAll();
}
}
返回成功:
2、登录失败处理器
/**
* 登陆失败的处理器
*/
@Component
public class AppAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Resource
private ObjectMapper objectMapper;
/**
* @param request 当前的请求对象
* @param response 当前的响应对象
* @param exception 失败的原因的异常
* @throws IOException
* @throws ServletException
*/
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
//设置响应编码
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
//返回JSON出去
HttpResult result=new HttpResult(-1,"登陆失败");
if(exception instanceof BadCredentialsException){
result.setData("密码不正确");
}else if(exception instanceof DisabledException){
result.setData("账号被禁用");
}else if(exception instanceof UsernameNotFoundException){
result.setData("用户名不存在");
}else if(exception instanceof CredentialsExpiredException){
result.setData("密码已过期");
}else if(exception instanceof AccountExpiredException){
result.setData("账号已过期");
}else if(exception instanceof LockedException){
result.setData("账号被锁定");
}else{
result.setData("未知异常");
}
//把result转成JSON
String json = objectMapper.writeValueAsString(result);
//响应出去
PrintWriter out = response.getWriter();
out.write(json);
out.flush();
}
}
关于AuthenticationException异常的继承关系:Ctrl+H
3、无权限处理器
/**
* 无权限的处理器
*/
@Component
public class AppAccessDeniedHandler implements AccessDeniedHandler {
@Resource
private ObjectMapper objectMapper;
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
//设置响应编码
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
//返回JSON出去
HttpResult result=new HttpResult(403,"无权限访问");
//把result转成JSON
String json = objectMapper.writeValueAsString(result);
//响应出去
PrintWriter out = response.getWriter();
out.write(json);
out.flush();
}
}
4、登出(退出)处理器
/**
* 退出成功的处理器
*/
@Component
public class AppLogoutSuccessHandler implements LogoutSuccessHandler {
@Resource
private ObjectMapper objectMapper;
/**
*
* @param request
* @param response
* @param authentication 当前退出的用户对象
* @throws IOException
* @throws ServletException
*/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//设置响应编码
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
//返回JSON出去
HttpResult result=new HttpResult(200,"退出成功");
//把result转成JSON
String json = objectMapper.writeValueAsString(result);
//响应出去
PrintWriter out = response.getWriter();
out.write(json);
out.flush();
}
}
5、安全配置类WebSecurityConfig
最后修改下安全配置类,把上面定义的处理器加进来,完成逻辑闭环:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 注入登陆成功的处理器
@Autowired
private MyAutheticationSuccessHandle successHandler;
// 注入登陆失败的处理器
@Autowired
private AppAuthenticationFailureHandler failureHandler;
// 注入没有权限的处理器
@Autowired
private AppAccessDeniedHandler accessDeniedHandler;
// 注入退出成功的处理器
@Autowired
private AppLogoutSuccessHandler logoutSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
http.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler)
.permitAll();
http.logout()
.logoutSuccessHandler(logoutSuccessHandler);
http.authorizeRequests()
.mvcMatchers("/teacher/**")
.hasRole("teacher")
.anyRequest()
.authenticated();
}
}
重启服务后,访问没权限的资源: