Shrio是一个轻量级的,基于AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。
JWT(JSON Web Token)是目前最流行的跨域身份验证解决方案,具有加密和自包含的特性。
1.maven配置
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
2.自定义Token Authentication
package com.bby.security; import org.apache.shiro.authc.AuthenticationToken; /** * 自定义jwt类型的token * * @author: zhangyang * @create: 2018/11/28 8:39 **/ public class MyJWTToken implements AuthenticationToken { private String token; public MyJWTToken(String token) { this.token = token; } @Override public Object getPrincipal() { return token; } @Override public Object getCredentials() { return token; } }
3.自定义Shiro过滤器
package com.bby.security; import com.alibaba.fastjson.JSONObject; import com.bby.common.vo.Result; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.util.AntPathMatcher; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.PrintWriter; /** * jwt token filter * * @Author zhangyang * @Date 下午 8:42 2018/11/27 0027 **/ @Slf4j public class MyJWTFilter extends BasicHttpAuthenticationFilter { private String tokenHeader; private String loginUri; public MyJWTFilter(String tokenHeader, String loginUri) { this.tokenHeader = tokenHeader; this.loginUri = loginUri; } /** * 如果是登录则直接放行; * 如果带有 token,则对 token 进行检查 * * @param request * @param response * @param mappedValue * @return */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { HttpServletRequest req = (HttpServletRequest) request; AntPathMatcher matcher = new AntPathMatcher(); // 开放登录接口访问 if (matcher.match(loginUri, req.getRequestURI())) { return true; } // 判断请求的请求头是否带上token if (StringUtils.isBlank(req.getHeader(tokenHeader))) { return false; } // 如果存在,则进入 executeLogin 方法执行登入,检查 token 是否正确 try { executeLogin(request, response); } catch (Exception e) { log.error(e.getMessage()); try { // globalExceptionHandler无法处理filter中的异常,这里手动处理 PrintWriter out = response.getWriter(); out.print(JSONObject.toJSON(Result.failureWithCode(Result.UNAUTHORIZED, e.getMessage()))); out.flush(); } catch (IOException e1) { e1.printStackTrace(); } return false; } return true; } /** * 执行登陆操作 * * @param request * @param response * @return */ @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String token = httpServletRequest.getHeader(tokenHeader); MyJWTToken jwtToken = new MyJWTToken(token); // 提交给realm进行登入,如果错误他会抛出异常并被捕获 getSubject(request, response).login(jwtToken); // 如果没有抛出异常则代表登入成功,返回true return true; } }