怎么通过注解实现shiro不校验url
- shiro学习系列
- 时间:2023-06-12 15:54
- 3855人已阅读
简介
在使用shiro的权限认证的时候,有时候,有些链接不需要shiro认证的。比如登录接口。在代码中写死,如下图:每次,有新的不需要认证的,都需要添加,忘了手动添加就会出问题。能不能添加一个自定义注解,在不需要shiro认证的方法或者类上直接加自定义注解来处理?答案:可以。以下为解决步骤:①:添加自定义注解import java.lang.annotation.ElementType;imp
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
在使用shiro的权限认证的时候,有时候,有些链接不需要shiro认证的。比如登录接口。在代码中写死,如下图:
每次,有新的不需要认证的,都需要添加,忘了手动添加就会出问题。能不能添加一个自定义注解,在不需要shiro认证的方法或者类上直接加自定义注解来处理?
答案:可以。
以下为解决步骤:
①:添加自定义注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ShiroIgnoreAuth { }
②:在进行权限校验时,可以通过判断方法上是否有 @ShiroIgnoreAuth
注解来决定是否进行权限校验。
例如:
完整的代码如下:
import xxx.LoginServiceImpl; import xxx.ShiroIgnoreAuth; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpStatus; import org.springframework.web.method.HandlerMethod; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.support.RequestContextUtils; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Method; @Slf4j public class JwtFilter extends BasicHttpAuthenticationFilter { /** * 执行登录认证 */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; WebApplicationContext ctx = RequestContextUtils.findWebApplicationContext(httpServletRequest); RequestMappingHandlerMapping mapping = ctx.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); HandlerExecutionChain handler = null; try { handler = mapping.getHandler(httpServletRequest); HandlerMethod handlerClass = (HandlerMethod)handler.getHandler(); Class<?> nowClass = handlerClass.getBeanType(); Method method = handlerClass.getMethod(); ShiroIgnoreAuth anonymousAccess = AnnotationUtils.getAnnotation(nowClass, ShiroIgnoreAuth.class); if (anonymousAccess != null) { return true; } anonymousAccess = AnnotationUtils.getAnnotation(method,ShiroIgnoreAuth.class); //如果方法上有 @ShiroIgnoreAuth 注解,则不进行权限校验 if (anonymousAccess != null) { return true; } //执行登录 executeLogin(request, response); return true; } catch (AuthenticationException e) { log.error("认证失败",e); response401(request, response, e.getMessage()); } catch (Exception e) { //如果没有token,那么就请求转发到到401请求,让401controller返回前端一个请求 log.error("认证异常",e); response401(request, response, "其他异常"); } return false; } /** * Jwt登录 */ @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String token = httpServletRequest.getHeader(LoginServiceImpl.X_ACCESS_TOKEN); JwtToken jwtToken = new JwtToken(token); // 提交给realm进行登入,如果错误他会抛出异常并被捕获 getSubject(request, response).login(jwtToken); // 如果没有抛出异常则代表登入成功,返回true return true; } /** * 对跨域提供支持 */ @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE"); httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态 if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { httpServletResponse.setStatus(HttpStatus.OK.value()); return false; } return super.preHandle(request, response); } /** * 重定向到 * * @param request * @param response * @param msg */ private void response401(ServletRequest request, ServletResponse response , String msg) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; try { // //请求转发401controller httpServletRequest.getRequestDispatcher("/login/401/" + msg).forward(request, response); } catch (ServletException | IOException e) { log.error("重定向时候异常了",e); } } }