package com.landtool.lanbase.common.shiro; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpStatus; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.StringUtils; import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMethod; import com.google.gson.Gson; import com.landtool.lanbase.common.utils.HttpUtils; import com.landtool.lanbase.common.utils.Result; /** * @author lanbase * @Description: TODO(shiro 认证过滤器) * @date 2017-6-23 15:07 */ public class ShiroAuthenticatingFilter extends AuthenticatingFilter { private static String loginUrl; // http://127.0.0.1:8082/login private static String CasHost;// https://cas.nmsmp.com/cas/ private Logger logger = LoggerFactory.getLogger(getClass()); public ShiroAuthenticatingFilter(String loginUrl,String casHost) { this.loginUrl=loginUrl; this.CasHost=casHost; } // 创建shiro认证的token @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpRequest = (HttpServletRequest) request; String username = httpRequest.getRemoteUser(); // 获取请求token String token = getRequestToken((HttpServletRequest) request); ShiroToken shiroToken = null; // if (!StringUtils.isBlank(token)) { // shiroToken = new ShiroToken(token); // } else if (!StringUtils.isBlank(username)) { // shiroToken = new ShiroToken(username, true); // } else { // return null; // } return shiroToken; } // protected boolean preHandle(ServletRequest request, ServletResponse // response) throws Exception { // HttpServletRequest httpRequest = WebUtils.toHttp(request); // HttpServletResponse httpResponse = WebUtils.toHttp(response); // if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { // httpResponse.setHeader("Access-control-Allow-Origin", origin); // httpResponse.setHeader("Access-Control-Allow-Methods", // httpRequest.getMethod()); // httpResponse.setHeader("Access-Control-Allow-Headers", // httpRequest.getHeader("Access-Control-Request-Headers")); // httpResponse.setStatus(HttpStatus.OK.value()); // return false; // } // return super.preHandle(request, response); // } // 是否允许访问 @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { return false; } // 拒绝访问的出来 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 处理CORS的options请求 by Tanbin if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { String origin = httpRequest.getHeader("Origin"); httpResponse.setHeader("Access-control-Allow-Origin", origin); httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod()); httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers")); httpResponse.setStatus(HttpStatus.SC_OK); return false; } String username = httpRequest.getRemoteUser(); if (StringUtils.hasText(username)) {// 已经登录shiro logger.debug("0----已经登录shiro:" + username); return true ; } else { username = getLoginNamefromXml(httpRequest); if (StringUtils.hasText(username)) { Subject subject = SecurityUtils.getSubject(); ShiroToken shiroToken = new ShiroToken(username, true); if(!subject.isAuthenticated()) { subject.login(shiroToken); logger.debug("8----loginshiro:" ); } String redirectUrl= getValidateTicketServer(httpRequest); logger.debug("3----RedirectOldurl:" + redirectUrl); //WebUtils.issueRedirect(request, response, oldUrl); httpResponse.setHeader("P3P", "CP=CAO PSA OUR"); httpResponse.sendRedirect(redirectUrl); } else { String reloginUrl= getFirstServer(httpRequest); reloginUrl= CasHost + "login?service="+URLEncoder.encode( reloginUrl); logger.debug("1----RedirectCasloginUrl:" + reloginUrl); httpResponse.sendRedirect(reloginUrl);// 用户名不存在跳转回登录页面 return false; } } return true ; } @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setContentType("application/json;charset=utf-8"); try { // 处理登录失败的异常 Throwable throwable = e.getCause() == null ? e : e.getCause(); Result r = Result.error(HttpStatus.SC_UNAUTHORIZED, throwable.getMessage()); String json = new Gson().toJson(r); httpResponse.getWriter().print(json); } catch (IOException e1) { } return false; } /** * 获取请求的token */ private String getRequestToken(HttpServletRequest httpRequest) { // 从header中获取token String token = httpRequest.getHeader("token"); // 如果header中不存在token,则从参数中获取token if (!StringUtils.hasText(token)) { token = httpRequest.getParameter("token"); } return token; } private String getLoginNamefromXml(HttpServletRequest request) throws Exception { String username = ""; Subject subject = SecurityUtils.getSubject(); Session session =subject.getSession(true); username = session.getAttribute("shirousername") == null ? "" : session.getAttribute("shirousername").toString(); logger.debug("4----shirousername:" + session.getAttribute("shirousername") +(session.getId() )); if (org.springframework.util.StringUtils.isEmpty(username)) { String ticket = request.getParameter("ticket"); if (!org.springframework.util.StringUtils.isEmpty(ticket)) { String reloginUrl= getValidateTicketServer(request); String url = CasHost.replace("https", "http"); String validateurl = url + "serviceValidate?ticket=" + ticket + "&service=" + URLEncoder.encode(reloginUrl); logger.debug("2----ServiceValidate:" + validateurl); String casxml; casxml = HttpUtils.get(validateurl); logger.debug(casxml); Integer index = casxml.indexOf(""); Integer end = casxml.indexOf(""); if (index > 0) { username = casxml.substring(index + 10, end); } } } return username; } private String getValidateTicketServer(HttpServletRequest request) { String server = getServerParameter(request); String reloginUrl= request.getRequestURL().toString(); if(StringUtils.hasText( server)) { reloginUrl+="?"+server; } return reloginUrl; } private String getServerParameter(HttpServletRequest request) { String server = request.getQueryString(); String ticket = request.getParameter("ticket"); if (!org.springframework.util.StringUtils.isEmpty(ticket)) { server = server.replace("ticket=" + ticket, ""); if (server.endsWith("&")) server = server.substring(0, server.length() - 1); } return server; } /*** * 获取原始访问路径 * * @return */ private String getFirstServer(HttpServletRequest httpRequest) { String reloginUrl= httpRequest.getRequestURL().toString(); if(StringUtils.hasText( httpRequest.getQueryString())) { reloginUrl+="?"+httpRequest.getQueryString(); } return reloginUrl; } }