shrio
1.概述
一个基于token的权限认证组件,适用于api和web两种场景。
2.使用demo
配置三个filter,全局filter用于组织没有权限的请求,apiLoginFilter用于处理api的登录请求,uiLoginFilter用于处理来自界面的登录请求。
1).全局filter
public class GlobalFilter extends FormAuthenticationFilter { Logger log = LoggerFactory.getLogger(GlobalFilter.class); private AntPathMatcher antPathMatcher =new AntPathMatcher(); private static final Logger _logger = LoggerFactory.getLogger(GlobalFilter.class); protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception { WebUtils.issueRedirect(request, response, "/", null, true); } @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {return super.preHandle(request, response); } //保存异常对象到request @Override protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) { request.setAttribute(getFailureKeyAttribute(), ae); } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { boolean isAccessAllowed=false; Subject subject = getSubject(request, response); HttpServletRequest req = (HttpServletRequest) request; String requestURI = req.getRequestURI(); if(antPathMatcher.match("/webui/login",requestURI)||antPathMatcher.match("/api/login",requestURI)){//排除登录请求 return true; } return subject.isAuthenticated(); } }
对于没有权限的请求默认是跳转到登录页,如果不需要跳转而是返回异常或是别的处理可以重载onAccessDenied。
2).apiLoginFilter
public class ApiLoginFilter extends BasicHttpAuthenticationFilter{ Logger log = LoggerFactory.getLogger(ApiLoginFilter.class); private AntPathMatcher antPathMatcher =new AntPathMatcher(); @Override protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) { HttpServletRequest req = (HttpServletRequest) request; String authorization = req.getHeader("Authorization");return authorization == null; } @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String requestURI = httpServletRequest.getRequestURI(); String authorization = httpServletRequest.getHeader("Authorization"); JwtToken token = new JwtToken(authorization); getSubject(request, response).login(token); return true; } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { if (isLoginAttempt(request, response)) { try { executeLogin(request, response); } catch (Exception e) { e.printStackTrace(); response401(request, response); } } HttpServletRequest req = (HttpServletRequest) request; String requestURI = req.getRequestURI(); Subject subject = getSubject(request, response); return subject.isAuthenticated(); } }
另外需要设置一个realm来完成真正登录逻辑,
public class SelfRealm extends AuthorizingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String token = (String) authenticationToken.getCredentials(); // 解密获得username,用于和数据库进行对比 if(token!=null&&!"".equals(token.trim())){ String username = JWTUtil.getUsername(token); if (username == '123') {
return new SimpleAuthenticationInfo(user, user.getPassword(), "self");
}
return null; } }
3.shiro结构
以上为shiro的核心实现,web层认证只是向web的Filter中做了适配。