shiro整合前后端拆散的springboots,Vue我的项目真的是有很多大坑啊。

明天我的主题是:如何设置shiro过滤器。

遇到问题:我的我的项目是前后端拆散的,shiro外面有一个shiroFilterFactoryBean.setUnauthorizedUrl(“你本人的url”);
函数

这是什么意思呢:这示意如果你拜访了一个须要权限的url,然而目前你登陆的角色没有权限,那么页面默认跳转的地址。
看着仿佛是没啥故障。
然而!!!
如果是前后端拆散怎么办呢?后端shiro让我的项目跳向前端某个页面,这里是前后端分离式的啊!以后端的用户(没权限)发送了一个申请被shiro间接拦挡了,前端一脸懵不晓得产生什么问题了,所以傻傻的在控制台返回一段红色的跨域错误信息。
那么咱们应该怎么解决呢?
你必定会想那就让后端让前端跳转啊,这里我要说,既然是前后端拆散的话,后端只能给前端发送信息让前端依据返回的信息自行处理。
然而问题又来了,shiro这玩意间接把前端申请拦挡了啥都不返回,啥都不说一声,搞的前端还误会是跨域问题。

那么咱们就应该去改写shiro的拦截器,让它解决形式更人性化。

不废话了,开始主题

开始改写拦截器:

//package com.igeekhome.ccs.tool.config;  //写本人的当前目录import lombok.SneakyThrows;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authz.AuthorizationFilter;import org.springframework.boot.configurationprocessor.json.JSONObject;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;import java.io.PrintWriter;public class MyPermsFilter extends AuthorizationFilter {    @Override    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)            throws Exception {        System.out.println("isAccessDenied");        Subject subject = getSubject(request, response);        String[] rolesArray = (String[]) mappedValue;        System.out.println("subject:"+subject.getPrincipal());        if (rolesArray == null || rolesArray.length == 0) {            //no roles specified, so nothing to check - allow access.            return true;        }        for(int i=0;i<rolesArray.length;i++){            if(subject.isPermitted(rolesArray[i])){                System.out.println("rolealist:"+rolesArray[i]);                return true;            }        }        return false;    }    @SneakyThrows    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {        System.out.println("onAccessDenied");        Subject subject = getSubject(request, response);        response.setCharacterEncoding("UTF-8");        response.setContentType("text/html;charset=UTF-8");        // If the subject isn't identified, redirect to login URL        if (subject.getPrincipal() == null) {//            saveRequestAndRedirectToLogin(request, response);     //没登陆就进入从新登陆接口,这里前后端拆散不须要            System.out.println("没登陆");            String objectStr= "{'name':'没登陆'}";            JSONObject jsonObject=new JSONObject(objectStr);            PrintWriter wirte = null;            wirte = response.getWriter();            wirte.print(jsonObject);        } else {            System.out.println("没权限");            String objectStr= "{'name':'没权限'}";            JSONObject jsonObject=new JSONObject(objectStr);            PrintWriter wirte = null;            wirte = response.getWriter();            wirte.print(jsonObject);//            JSONObject json = new JSONObject();//            json.put("state","403");//            json.put("msg","登录已生效,请从新登录!");//            out.println(json);//            out.flush();//            out.close();        }        return false;    }}

首先看到

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)

也就是第一个函数
解释一下:这个函数每次shiro启动都会运行,看到参数ServletRequest request, ServletResponse response这两个参数是为以后用户身份确认起作用的,再看到Object mappedValue,它外面存在你之前shiro配置文件里存入的权限要求:

我这里存了一个:

filterChainDefinitionMap.put("/detail/getclass","perms[user:teacher]");

所以mappedValue里存的应该是user:teacher,当然前提是把它转化为String

再看到代码:

这是看看你之前有没有存权限,如果没存的话(列表大小为0或列表为空)返回true,shiro就不拦你了。
再往下看:

这里subject是什么?你往上看找到:

这个就是获取你以后登陆的用户。
而后留神了!

 if(subject.isPermitted(rolesArray[i])){                System.out.println("rolealist:"+rolesArray[i]);                return true;            }

这是干嘛,这就是拿以后用户判断isPermitted(),以后用户有没有perms的内容,也就是判断subject外面有没有”user:teacher”权限,而后这里有个大坑,网上基本上所有教程代码是这样的:

他们是hasRole,其实也没故障,然而我之前设置的是

perms所以要用isPermitted,你要发分明你加的是什么权限。
接着下一步:
如果找到了返回true,没找到从for循环进去,间接返回false。
false呈现了,怎么办呢?这时候第二个函数

protected boolean onAccessDenied(ServletRequest request, ServletResponse response) 

晓得你返回是false的话它就会运行,看红色框内

这代表什么意思,当然是获取以后用户的username了也就是标识码了,这里不懂得阐明shiro你还是没弄懂()因为之前的自定义Realm类用过了。
如果subject.getPrincipal() == null阐明没有用户名,意味着你还没有登陆呢,以前代码这里是一个跳转函数(让前端跳到登陆页面,然而我是前后端拆散所以没用!),这里我改成了

            String objectStr= "{'name':'没登陆'}";            JSONObject jsonObject=new JSONObject(objectStr);            PrintWriter wirte = null;            wirte = response.getWriter();            wirte.print(jsonObject);

这是把自定义的objectStr 字符串转化为jsob格局,而后用PrintWriter返回给前端,这样一旦出错那么shiro除了拦挡申请外还会给前端发一个 "{‘name’:‘没登陆’}“的json信息,这些前端就不懵了就不会说什么跨域问题了。而是失去了json数据。而后上面的else局部内容就不说了,和下面简直一样给前端发送一个”{‘name’:‘没权限’}"的信息,这意味着你权限出错了,并且用户也登陆了,那么就只有一个可能导致第一个函数返回false,那就是你原本就没有权限!

好了好了说了一大堆。

[](https://blog.csdn.net/lanlans...

老规矩,给那些赶时间的敌人们:

快餐:

总结:

三个点:
1.为什么要写拦截器,并且如何去重写拦截器,下面说了哦。
2.拦截器文件第一个函数里是用subject.isPermitted(rolesArray[i])还是subject.hasRole(rolesArray[i])依据本人在之前设置信息判断。

我用的perms所以用subject.isPermitted(rolesArray[i])

3.就是这么向前端返回数据信息

而后贴出四分代码:
shiroConfig:

package //本人的包;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;import java.util.LinkedHashMap;import java.util.Map;@Configurationpublic class shiroConfig {    @Bean(name = "shiroFilter")    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();        shiroFilterFactoryBean.setSecurityManager(securityManager);        shiroFilterFactoryBean.setLoginUrl("/index/login");        shiroFilterFactoryBean.setSuccessUrl("/Station/noauth");//        shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");         shiroFilterFactoryBean.setUnauthorizedUrl("/Station/noauth");//        shiroFilter.setLoginUrl("");//身份认证失败,则跳转到登录页面的配置 没有登录的用户申请须要登录的页面时主动跳转到登录页面,不是必须的属性,不输出地址的话会主动寻找我的项目web我的项目的根目录下的”/login.jsp”页面。//        shiroFilter.setSuccessUrl("");//登录胜利默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个须要登录的页面,则在登录主动跳转到那个须要登录的页面。不跳转到此。//        shiroFilter.setUnauthorizedUrl("");//没有权限默认跳转的页面//        shiroFilter.setFilterChainDefinitions("");//filterChainDefinitions的配置程序为自上而下,以最下面的为准        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();        // <!-- authc:所有url都必须认证通过才能够拜访; anon:所有url都都能够匿名拜访-->        filterChainDefinitionMap.put("/Station/**", "anon");        filterChainDefinitionMap.put("/index/**", "anon");//        filterChainDefinitionMap.put("/detail/**", "anon");//        filterChainDefinitionMap.put("/detail/**", "anon");//        filterChainDefinitionMap.put("/Goods/**", "authc");        //次要这行代码必须放在所有权限设置的最初,不然会导致所有 url 都被拦挡 残余的都须要认证//        filterChainDefinitionMap.put("/**", "authc");        filterChainDefinitionMap.put("/detail/getclass","perms[user:teacher]");        // 1、创立过滤器Map,用来装自定义过滤器        LinkedHashMap<String, Filter> map = new LinkedHashMap<>();        // 2、将自定义过滤器放入map中,如果实现了自定义受权过滤器,那就必须在这里注册,否则Shiro不会应用自定义的受权过滤器        map.put("perms", new MyPermsFilter());        // 3、将过滤器Ma绑定到shiroFilterFactoryBean上        shiroFilterFactoryBean.setFilters(map);        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);        return shiroFilterFactoryBean;    }    @Bean    public SecurityManager securityManager(CustomRealm realm){        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();        defaultWebSecurityManager.setRealm(realm);        return  defaultWebSecurityManager;    }    @Bean    public CustomRealm customRealm() {        CustomRealm customRealm = new CustomRealm();        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());        return customRealm;    }    @Bean    public HashedCredentialsMatcher hashedCredentialsMatcher(){        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();        // 应用md5 算法进行加密        hashedCredentialsMatcher.setHashAlgorithmName("md5");        // 设置散列次数: 意为加密几次        hashedCredentialsMatcher.setHashIterations(2);        return hashedCredentialsMatcher;    }}

CustomRealm:

package //本人的包;import com.igeekhome.ccs.biz.IndexBiz;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AccountException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import org.apache.tomcat.websocket.AuthenticationException;import org.springframework.beans.factory.annotation.Autowired;import java.util.HashSet;import java.util.Set;public class CustomRealm extends AuthorizingRealm {//    @Autowired//    private LoginService loginService;    @Autowired    IndexBiz indexBiz;    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        String username = (String) SecurityUtils.getSubject().getPrincipal();        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        Set<String> stringSet = new HashSet<>();        if (indexBiz.getsatte(username).equals("老师")){            System.out.println("老师");            stringSet.add("user:teacher");        }else {            System.out.println("学生");            stringSet.add("user:student");        }        info.setStringPermissions(stringSet);        return info;    }    /**     * 这里能够注入userService,为了不便演示,我就写死了帐号了明码     * private UserService userService;     * <p>     * 获取行将须要认证的信息     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {        System.out.println("-------身份认证办法--------");        String userName = (String) authenticationToken.getPrincipal();        String userPwd = new String((char[]) authenticationToken.getCredentials());        //依据用户名从数据库获取明码        String password = indexBiz.getpassword(userName);        if (indexBiz.getsatte(userName)==null) {            throw new AccountException("用户名谬误");        }//        else if (!userPwd.equals(password)) {//            throw new AccountException("明码不正确");//        }        String dbPwd = indexBiz.getpassword(userName);        return new SimpleAuthenticationInfo(userName,dbPwd, ByteSource.Util.bytes(userName + "salt"),getName());    }}

MyPermsFilter:

package //本人的包;import lombok.SneakyThrows;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authz.AuthorizationFilter;import org.springframework.boot.configurationprocessor.json.JSONObject;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;import java.io.PrintWriter;public class MyPermsFilter extends AuthorizationFilter {    @Override    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)            throws Exception {        System.out.println("isAccessDenied");        Subject subject = getSubject(request, response);        String[] rolesArray = (String[]) mappedValue;        System.out.println("subject:"+subject.getPrincipal());        if (rolesArray == null || rolesArray.length == 0) {            //no roles specified, so nothing to check - allow access.            return true;        }        for(int i=0;i<rolesArray.length;i++){            if(subject.isPermitted(rolesArray[i])){//subject.hasRole(rolesArray[i])                System.out.println("rolealist:"+rolesArray[i]);                return true;            }        }        return false;    }    @SneakyThrows    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {        System.out.println("onAccessDenied");        Subject subject = getSubject(request, response);        response.setCharacterEncoding("UTF-8");        response.setContentType("text/html;charset=UTF-8");        // If the subject isn't identified, redirect to login URL        if (subject.getPrincipal() == null) {//            saveRequestAndRedirectToLogin(request, response);     //没登陆就进入从新登陆接口,这里前后端拆散不须要            System.out.println("没登陆");            String objectStr= "{'name':'没登陆'}";            JSONObject jsonObject=new JSONObject(objectStr);            PrintWriter wirte = null;            wirte = response.getWriter();            wirte.print(jsonObject);        } else {            System.out.println("没权限");            String objectStr= "{'name':'没权限'}";            JSONObject jsonObject=new JSONObject(objectStr);            PrintWriter wirte = null;            wirte = response.getWriter();            wirte.print(jsonObject);//            JSONObject json = new JSONObject();//            json.put("state","403");//            json.put("msg","登录已生效,请从新登录!");//            out.println(json);//            out.flush();//            out.close();        }        return false;    }}

最初

文章的最初给大家安利一个福利,关注公众号:前程有光,支付一线大厂Java面试题总结+各知识点学习思维导+一份300页pdf文档的Java外围知识点总结!