# 6. 登录异常处理
使用过滤器 .failureForwardUrl("/login/error");
此前放在session里面,更新后放在了request里面 下载java源码后可以在源码上打断点了。 AuthenticationException 注意包名是import org.springframework.security.core.AuthenticationException;
@RequestMapping("/login/error")
public void loginError(HttpServletResponse response, HttpServletRequest request){
response.setCharacterEncoding("utf-8");
AuthenticationException authenticationException = (AuthenticationException)request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
try {
response.getWriter().write(authenticationException.getMessage());
}catch (IOException e){
e.printStackTrace();
}
}
效果 url还是http://127.0.0.1:8080/login,网页内容 Bad credentials
枚举类构造方法,统一错误代码 统一JSON返回格式,JsonResult(大袋子) 设置返回的格式为json
Spring Security自带一个login Controller
package com.zr.handler;
import com.alibaba.fastjson.JSON;
import com.zr.common.JsonResult;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write(JSON.toJSONString(JsonResult.success()));
}
}
添加:.successHandler(loginSuccessHandler); 移除:.defaultSuccessUrl("/home") // .failureForwardUrl("/login/error");
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write(JSON.toJSONString(JsonResult.fail(e.getMessage())));
}
}
public class UnLoginAuthentication implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write(JSON.toJSONString(JsonResult.fail(ResultCode.USER_NOT_LOGIN)));
}
}
继承
JsonResult.fail()可以直接接收枚举
@Component
public class UrlAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write(JSON.toJSONString(JsonResult.fail(ResultCode.NO_PERMISSION)));
}
}
.passwordParameter("password")
.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler)
.and()
.exceptionHandling()
.authenticationEntryPoint(unLoginAuthentication)
.accessDeniedHandler(urlAccessDeniedHandler);
自带controller,.logoutUrl("/logout")配置访问路径
@Component
public class UrlLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
httpServletResponse.getWriter().write(JSON.toJSONString(JsonResult.success()));
}
}
.and()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessHandler(urlLogoutSuccessHandler);
参考 https://blog.csdn.net/ChineseSoftware/article/details/118414906
@PostMapping("/list")
@PreAuthorize("hasAnyAuthority('sys:user:list')")
public JsonResult list(@RequestBody SysUser sysUser){
return JsonResult.success("查询成功");
}
@PostMapping("/add")
@PreAuthorize("hasAnyRole('ROLE_user')")
public JsonResult add(@RequestBody SysUser sysUser){
return JsonResult.success("新增成功");
}
导包 关闭session
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
权限不写在payload里面,存储在redis里面
需要每次请求时携带jwt
package com.zr.filter;
import com.alibaba.fastjson.JSON;
import com.zr.utils.JWTUtil;
import com.zr.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.token-header-key}")
private String tokenHeaderKey;
@Autowired
private JWTUtil jwtUtil;
@Autowired
private RedisUtil redisUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader(tokenHeaderKey);
if(token == null){
filterChain.doFilter(request, response);
}else{
String loginKey = jwtUtil.getRedisToken(token);
String data = redisUtil.get(loginKey);
if(data == null){
//超时处理。。。
filterChain.doFilter(request, response);
}else{
User user = JSON.parseObject(data, User.class);
UsernamePasswordAuthenticationToken tokenBean = new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(tokenBean);
filterChain.doFilter(request, response);
}
}
}
}