美文网首页Java 杂谈shiro
spring boot 集成shiro之ajax返回json数据

spring boot 集成shiro之ajax返回json数据

作者: Wocus | 来源:发表于2019-09-17 19:48 被阅读0次

要解决ajax请求返回数据,问题很简单,比如你没有登录,去请求数据的时候,shiro指定了一个登录界面,会自动重定向那个界面,使用ajax请求的时候,需要返回数据为json格式这时候可以这么做:
编写一个接口:

@GetMapping("/401")
    public ResultData notLogin(){
        return ResultData.resultMsg(-104,"请先登录");
    }

然后把登录url设置成这个,返回的就是json格式的数据了,但是问题来了,当你跨域请求的时候,会报错,即使你设置了全局跨域,ajax请求首先会发送一个option请求,测试该链接是否能用,再来请求数据,这个时候,会报错,说不允许重定向,于是需要再shiro过滤器中改造以下,重继承FormAuthenticationFilter类,重写preHandle,onAccessDenied方法

    //判断是否是option请求,是就直接放行
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            setHeader(httpRequest,httpResponse);
            return true;
        }
        return super.preHandle(request,response);
    }

    /**
     * 在访问controller前判断是否登录,返回json,不进行重定向。
     * @param request
     * @param response
     * @return true-继续往下执行,false-该filter过滤器已经处理,不继续执行其他过滤器
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json");
            httpServletResponse.getWriter().write(JSONObject.toJSONString(ResultData.resultMsg(-104,"请先登录")));
        return false;
    }

然后再权限配置中,使用自定义的过滤器

package com.sansence.redwine.config;

import com.sansence.redwine.shiro.MyAuthenticationFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @program: shiro03
 * @description: 权限配置
 * @author: jiang wei
 * @create: 2019-04-24 14:13
 */
//@Configuration
public class ShiroConfig {

    /**
     * 配置接口权限
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //shiroFilterFactoryBean.setLoginUrl("/admin-info/401");//设置登录界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/manager/login.html");//设置无权限界面
        //设置自定义过滤器
        Map<String, Filter> filter = new LinkedHashMap<>();
        filter.put("authc",new ShiroLoginFilter());
        shiroFilterFactoryBean.setFilters(filter);
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/logs/**","authc");
        filterMap.put("/product/**","authc");
        filterMap.put("/admin-info/login","anon");
        filterMap.put("/admin-info/401","anon");
        filterMap.put("/admin-info/**","authc");
        filterMap.put("/adminware/**","authc");
        filterMap.put("/unit/**","authc");
        filterMap.put("/customer/**","authc");
        filterMap.put("/repertory/**","authc");
        filterMap.put("/role/**","authc");
        filterMap.put("/permission/**","authc");
        filterMap.put("/species/**","authc");
        filterMap.put("/user/**","authc");
        filterMap.put("/userrecord/**","authc");
        filterMap.put("/ware/**","authc");
        filterMap.put("/warerecord/**","authc");
        filterMap.put("/**","anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 注入权限管理
     * @return
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm(customRealm());
        return securityManager;
    }

    @Bean
    public CustomRealm customRealm(){
        return new CustomRealm();
    }
}

这个时候,你请求数据,还会报错,说跨域问题,于是需要继续改造,继续再自定义过滤器中写跨域处理,贴过滤器完整代码

package com.sansence.redwine.config;

import com.alibaba.fastjson.JSONObject;
import com.sansence.redwine.util.ResultData;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ShiroLoginFilter extends FormAuthenticationFilter {


    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            setHeader(httpRequest,httpResponse);
            return true;
        }
        return super.preHandle(request,response);
    }

    /**
     * 在访问controller前判断是否登录,返回json,不进行重定向。
     * @param request
     * @param response
     * @return true-继续往下执行,false-该filter过滤器已经处理,不继续执行其他过滤器
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        setHeader(httpRequest,httpResponse);
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json");
            httpServletResponse.getWriter().write(JSONObject.toJSONString(ResultData.resultMsg(-104,"请先登录")));
        return false;
    }

    /**
     * 为response设置header,实现跨域
     */
    private void setHeader(HttpServletRequest request,HttpServletResponse response){
        //跨域的header设置
        response.setHeader("Access-control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "*");
        //防止乱码,适用于传输JSON数据
        //Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild
        response.setHeader("Content-Type","application/json;charset=UTF-8");
        response.setStatus(HttpStatus.OK.value());
    }
}

除此之外,还要配置cors,贴上代码

package com.sansence.redwine.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class CORSConfiguration {
    @Bean
    public WebMvcConfigurer CORSConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*")
                        //设置是否允许跨域传cookie
                        .allowCredentials(true)
                        //设置缓存时间,减少重复响应
                        .maxAge(3600);
            }
        };
    }
}

问题解决,可以正常访问数据,而且未登录的时候是以json格式返回的,无权限设置json返回同理继承PermissionsAuthorizationFilter,实现方法和验证身份返回json一样,过滤器perms使用自定义过滤器。
但是最后还有一个问题,跨域的时候,ajax请求数据,是属于一次性的请求,还是无法验证身份,这时候需要回传token,服务器继承DefaultWebSecurityManager,重写里面的方法,来验证token是否可用以及鉴权,
这个问题,下一章再做讲解

相关文章

网友评论

    本文标题:spring boot 集成shiro之ajax返回json数据

    本文链接:https://www.haomeiwen.com/subject/qomcuctx.html