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