Shiro+SpringBoot前后端分离中跨域,sessionId,302问题


1.解决跨域
@Configuration
public class CorsConfig { public CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); //允许任何域名 corsConfiguration.addAllowedHeader("*"); //允许任何头 corsConfiguration.addAllowedMethod("*"); //允许任何方法 return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); //注册 return new CorsFilter(source); }
}
2.解决sessionId不一致问题,配置shiro,重写获取sessionId方法 //自定义的 shiro session 缓存管理器,用于跨域等情况下使用 token 进行验证,不依赖于sessionId(在shiroConfig中添加)
@Bean
public DefaultWebSessionManager getDefaultWebSessionManager() { MySessionManager defaultWebSessionManager = new MySessionManager(); defaultWebSessionManager.setSessionDAO(new MemorySessionDAO()); return defaultWebSessionManager; } //shiro 的 session 管理(单独写一个类) //自定义session规则,实现前后分离,在跨域等情况下使用token 方式进行登录验证才需要,否则没必须使用本类。 //(shiro默认使用 ServletContainerSessionManager 来做 session 管理,它是依赖于浏览器的 cookie 来维护 session 的,调用 storeSessionId 方法保存sesionId 到 cookie中)。 //为了支持无状态会话,我们就需要继承 DefaultWebSessionManager //自定义生成sessionId 则要实现 SessionIdGenerator public class MySessionManager extends DefaultWebSessionManager { private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; public MySessionManager() { super(); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { String id = WebUtils.toHttp(request).getHeader("Access-Token"); //如果请求头中有 token 则其值为sessionId if (!StringUtils.isEmpty(id)) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); return id; } else { //否则按默认规则从cookie取sessionId return super.getSessionId(request, response); } } }
3.解决登录302问题 public class UserAuthenticationFilter extends FormAuthenticationFilter {
    /**
     * 直接过滤可以访问的请求类型
     */
    private static final String REQUET_TYPE = "OPTIONS";

    public UserAuthenticationFilter() {
        super();
    }

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (((HttpServletRequest) request).getMethod().toUpperCase().equals(REQUET_TYPE)) {
            return true;
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }

    /**
     * 解决302
     * @param request
     * @param response
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                return executeLogin(request, response);
            } else {
                return true;
            }
        }else {
            //解决 WebUtils.toHttp 往返回response写数据跨域问题
            HttpServletRequest req =  WebUtils.toHttp(request);
            String origin = req.getHeader("Origin");
            HttpServletResponse resp = WebUtils.toHttp(response);
            resp.setHeader("Access-Control-Allow-Origin", origin);
            //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie
            //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域
            resp.setHeader("Access-Control-Allow-Credentials", "true");
            // 返回固定的JSON串
            ObjectMapper mapper = new ObjectMapper();
            WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
            WebUtils.toHttp(response).getWriter().print(mapper.writeValueAsString(100));
            return false;
        }

    }

}
4.解决权限不足302问题 public class UserAuthorizationFilter extends PermissionsAuthorizationFilter {
    /**
     * 根据请求接口路径进行验证
     * @param request
     * @param response
     * @param mappedValue
     * @return
     * @throws IOException
     */
    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        // 获取接口请求路径
        String servletPath = WebUtils.toHttp(request).getServletPath();
        mappedValue = new String[]{servletPath};
        return super.isAccessAllowed(request, response, mappedValue);
    }

    /**
     * 解决权限不足302问题
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() != null) {
            return true;
        } else {

            //解决 WebUtils.toHttp 往返回response写数据跨域问题
            HttpServletRequest req = (HttpServletRequest) request;
            String origin = req.getHeader("Origin");
            HttpServletResponse resp = (HttpServletResponse) response;
            resp.setHeader("Access-Control-Allow-Origin", origin);
            //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie
            //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域
            resp.setHeader("Access-Control-Allow-Credentials", "true");

            WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
            WebUtils.toHttp(response).getWriter().print("401");
        }
        return false;
    }

}

 参考:https://blog.csdn.net/wmy_0707/article/details/100118329?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-3&spm=1001.2101.3001.4242 

            https://blog.csdn.net/China_hdy/article/details/97154272


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM