日韩精品欧美激情国产一区_中文无码精品一区二区三区在线_岛国毛片AV在线无码不卡_亞洲歐美日韓精品在線_使劲操好爽好粗视频在线播放_日韩一区欧美二区_八戒八戒网影院在线观看神马_亚洲怡红院在线色网_av无码不卡亚洲电影_国产麻豆媒体MDX

Shiro 認證、授權(quán)失敗返回JSON數(shù)據(jù)

時間:2022-12-09 22:52:45 類型:JAVA
字號:    

在前后端分離的應用中,需要shiro授權(quán)失敗時,返回json格式數(shù)據(jù), 如下是在springboot應用中,前端ajax請求, shiro授權(quán)失敗,返回json數(shù)據(jù)的應用實例

1,  在ShiroFilterFactoryBean類中增加如下兩行代碼:

    1.png

2, 當然同時需要定義兩個角色和權(quán)限返回json類

    2.1  CustomRolesAuthorizationFilter  類

import com.alibaba.fastjson.JSONObject;
import com.zhuangzi.springboot1101.configurations.JsonResult;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;

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

public class CustomRolesAuthorizationFilter extends AuthorizationFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object o) throws Exception {
        Subject subject = getSubject(req, resp);
        String[] rolesArray = (String[]) o;

        if (rolesArray == null || rolesArray.length == 0) { //沒有角色限制,有權(quán)限訪問
            return true;
        }
        for (int i = 0; i < rolesArray.length; i++) {
            if (subject.hasRole(rolesArray[i])) { //若當前用戶是rolesArray中的任何一個,則有權(quán)限訪問
                return true;
            }
        }
        return false;
    }
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String requestedWith = request.getHeader("x-requested-with");
        if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
            return true;
        } else {
            return false;
        }
    }
    /***
     * 請求過濾的回調(diào)方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
            //未登錄
            if (isAjaxRequest((HttpServletRequest)request)) {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                JsonResult jsonResult = new JsonResult();
                jsonResult.setCode("401");
                jsonResult.setMsg("登錄認證失效,請重新登錄!");
                response.getWriter().write(JSONObject.toJSONString(jsonResult));
            }else {
                saveRequestAndRedirectToLogin(request, response);
            }
        } else {
            //已經(jīng)登陸,沒有權(quán)限
            String unauthorizedUrl = getUnauthorizedUrl();
            if(isAjaxRequest((HttpServletRequest)request)) {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                JsonResult jsonResult = new JsonResult();
                jsonResult.setCode("401");
                jsonResult.setMsg("您沒有權(quán)限執(zhí)行該操作");
                response.getWriter().write(JSONObject.toJSONString(jsonResult));
            }else {
                if (StringUtils.hasText(unauthorizedUrl)) {
                    WebUtils.issueRedirect(request, response, unauthorizedUrl);
                } else {
                    WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
                }
            }
        }
        return false;
    }
}

 2.2  CustomPermsAuthorizationFilter  類

import com.alibaba.fastjson.JSONObject;
import com.zhuangzi.springboot1101.configurations.JsonResult;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;

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

public class CustomPermsAuthorizationFilter extends PermissionsAuthorizationFilter {
    @Override
    public boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object o) {
        Subject subject = getSubject(req, resp);
        String[] rolesArray = (String[]) o;

        if (rolesArray == null || rolesArray.length == 0) { //沒有角色限制,有權(quán)限訪問
            return true;
        }
        for (int i = 0; i < rolesArray.length; i++) {
            if (subject.hasRole(rolesArray[i])) { //若當前用戶是rolesArray中的任何一個,則有權(quán)限訪問
                return true;
            }
        }
        return false;
    }
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String requestedWith = request.getHeader("x-requested-with");
        if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
            return true;
        } else {
            return false;
        }
    }
    /***
     * 請求過濾的回調(diào)方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
            //未登錄
            if (isAjaxRequest((HttpServletRequest)request)) {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                JsonResult jsonResult = new JsonResult();
                jsonResult.setCode("401");
                jsonResult.setMsg("登錄認證失效,請重新登錄!");
                response.getWriter().write(JSONObject.toJSONString(jsonResult));
            }else {
                saveRequestAndRedirectToLogin(request, response);
            }
        } else {
            //已經(jīng)登陸,沒有權(quán)限
            String unauthorizedUrl = getUnauthorizedUrl();
            if(isAjaxRequest((HttpServletRequest)request)) {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                JsonResult jsonResult = new JsonResult();
                jsonResult.setCode("401");
                jsonResult.setMsg("您沒有權(quán)限執(zhí)行該操作");
                response.getWriter().write(JSONObject.toJSONString(jsonResult));
            }else {
                if (StringUtils.hasText(unauthorizedUrl)) {
                    WebUtils.issueRedirect(request, response, unauthorizedUrl);
                } else {
                    WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
                }
            }
        }
        return false;
    }
}

順便附上ShiroConfig配置類 及MyRealm類

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class ShiroConfig {
    private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
    /**
     * 注入自定義的realm
     * @return MyRealm
     */
    @Bean
    // <bean id = 'myAuthRealm' class=>
    public MyRealm myAuthRealm() {
        MyRealm myRealm = new MyRealm();
        logger.info("====myRealm注冊完成=====");
        return myRealm;
    }

    /**
     * 注入安全管理器
     * @return SecurityManager
     */
    @Bean
    public SecurityManager securityManager() {
// 將自定義realm加進來
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myAuthRealm());
        logger.info("====securityManager注冊完成====");
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
// 定義shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
// 設(shè)置自定義的securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("roles", new CustomRolesAuthorizationFilter());
        filters.put("perms",new CustomPermsAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filters);

// 設(shè)置默認登錄的url,身份認證失敗會訪問該url
        shiroFilterFactoryBean.setLoginUrl("/login");
// 設(shè)置成功之后要跳轉(zhuǎn)的鏈接
        shiroFilterFactoryBean.setSuccessUrl("/success");
// 設(shè)置未授權(quán)界面,權(quán)限認證失敗會訪問該url
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
// LinkedHashMap是有序的,進行順序攔截器配置
        Map<String,String> filterChainMap = new LinkedHashMap<>();
// 配置可以匿名訪問的地址,可以根據(jù)實際情況自己添加,放行一些靜態(tài)資源等,anon表示放行
        filterChainMap.put("/images/**", "authc");
        //在實際應用中, 這個身份攔截大致是:filterChainMap.put("/admin/**", "authc");
        //即所有/admin/開頭的url都必須 登陸 成功才有基本的資格訪問頁面

        // “/user/student” 開頭的需要角色認證,是“admin”才允許
        filterChainMap.put("/user/student/**", "roles[學生]");
        //測試,先用一個非學生角色登陸,訪問, 應該是無權(quán)訪問
        //     再使用一個學生角色訪問, 應該是可以訪問

        // “/user/teacher” 開頭的需要權(quán)限認證,是“user:create”才允許
        filterChainMap.put("/user/teacher*/**", "perms[\"user:add\"]");
        // 不同的角色可以有相同的權(quán)限,只有此權(quán)限就可以訪問, 不一定是必須是什么角色
        // user:* : 匹配 user : 任意值
        // user:add: 匹配 user:add
        filterChainMap.put("/user/**", "authc");


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        logger.info("====shiroFilterFactoryBean注冊完成====");
        return shiroFilterFactoryBean;
    }


}
import com.zhuangzi.springboot1101.entity.Users;
import com.zhuangzi.springboot1101.service.UsersService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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 javax.annotation.Resource;

//Realm : 領(lǐng)域
//        本實中實現(xiàn)了 有什么權(quán)限(包含 角色及權(quán)限, 身份認證)
public class MyRealm extends AuthorizingRealm {
    @Resource
    private UsersService usersService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 獲取用戶名
        String username = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
                                //授權(quán)信息
        // 給該用戶設(shè)置角色,角色信息存在t_role表中取
        authorizationInfo.setRoles(usersService.getRoles(username));
        System.out.println(usersService.getRoles(username));
        // 給該用戶設(shè)置權(quán)限,權(quán)限信息存在t_permission表中取
        authorizationInfo.setStringPermissions(usersService.getPermissions(username));
        System.out.println("權(quán)限是:" + usersService.getPermissions(username));
        return authorizationInfo;

    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 根據(jù)token獲取用戶名,如果您不知道該該token怎么來的,先可以不管,下文會解釋
        String username = (String) authenticationToken.getPrincipal();
// 根據(jù)用戶名從數(shù)據(jù)庫中查詢該用戶
        Users users = usersService.getByUsername(username);
        if(users != null) {
// 把當前用戶存到session中
            SecurityUtils.getSubject().getSession().setAttribute("user", users);
// 傳入用戶名和密碼進行身份認證,并返回認證信息
            AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(users.getUsername(), users.getUserpwd(), "myRealm");
            return authcInfo;
        } else {
            return null;
        }

    }
}


<