• 分享知识-快乐自己:Shrio 案例Demo概述


    Shiro 权限认证核心:

    POM:文件:

    <!--shiro-all-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-all</artifactId>
        <version>1.2.3</version>
    </dependency>
    <!-- 添加shrio-web支持 -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.2.4</version>
    </dependency>
    <!-- 添加shrio-spring支持 -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.2.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.4.0</version>
    </dependency>

    WEB.XML:

    <!--01.配置 Shiro 的 ShiroFilter-->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    spring-shiro.xml 配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="    
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd  
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
        <!-- 自定义Realm -->
        <bean id="myRealm"
            class="com.dsj.gdbd.controller.shiro.realm.MyRealm">
            <property name="credentialsMatcher">
                <bean
                    class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                    <property name="hashAlgorithmName" value="MD5"></property>
                    <property name="hashIterations" value="1"></property>
                </bean>
            </property>
        </bean>
    
        <bean id="securityManager"
            class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!-- 注入realm -->
            <property name="realm" ref="myRealm" />
        </bean>
    
        <!-- 开启Shiro注解 -->
        <bean
            class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager" />
        </bean>
    
        <!-- 重写Shiro登录过滤器 -->
        <bean id="loginAgainFilter"
            class="com.dsj.gdbd.controller.shiro.filter.MyFormAuthenticationFilter"></bean>
        <bean id="shiroFilter"
            class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!-- Shiro的核心安全接口,这个属性是必须的 -->
            <property name="securityManager" ref="securityManager" />
    
            <!-- 身份认证失败,则跳转到登录页面的配置(这里的路径与 form 表单路径一致,并且是 POST 请求) -->
            <property name="loginUrl" value="/login/to_login" />
    
            <!-- 权限认证失败,则跳转到指定页面 -->
            <property name="unauthorizedUrl"
                value="/login/to_unauthorized" />
    
            <!-- 权限认证成功,则跳转到指定页面 -->
            <property name="successUrl" value="/home/to_index" />
    
            <property name="filters">
                <map>
                    <entry key="mauthc" value-ref="loginAgainFilter" />
                    <entry key="logout">
                        <!-- 退出之后的重定向地址 -->
                        <bean class="org.apache.shiro.web.filter.authc.LogoutFilter">
                            <property name="redirectUrl" value="/login/to_login" />
                        </bean>
                    </entry>
                </map>
            </property>
    
            <property name="filterChainDefinitions">
                <value>
    
                    <!-- anon 表示可以匿名使用。 -->
                    /static/**=anon
    
                    /login/to_login=mauthc
                    /login/logout=logout
                    /login/**=anon
                    <!-- authc表示需要认证(登录)才能使用 -->
                    /** = authc
                </value>
            </property>
        </bean>
    
    </beans>

    重写Shiro登录过滤器 :

    package com.dsj.gdbd.controller.shiro.filter;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
    
    public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
        //重写登录成功
        @Override
        protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
                ServletResponse response) throws Exception {
            //开启授权
            subject.hasRole("*");
            
            return super.onLoginSuccess(token, subject, request, response);
        }
    }

    MyRealm.java  验证授权:

    package com.dsj.gdbd.controller.shiro.realm;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.dsj.gdbd.pojo.MenuFunction;
    import com.dsj.gdbd.pojo.RoleInfo;
    import com.dsj.gdbd.pojo.UserInfo;
    import com.dsj.gdbd.service.MenuFunctionService;
    import com.dsj.gdbd.service.RoleInfoService;
    import com.dsj.gdbd.service.UserInfoService;
    import com.dsj.gdbd.utils.enums.DeleteStatusEnum;
    
    public class MyRealm extends AuthorizingRealm {
        @Autowired
        private UserInfoService userInfoService;
        @Autowired
        private RoleInfoService roleInfoService;
        @Autowired
        private MenuFunctionService menuFunctionService;
        private final Logger LOGGER = LoggerFactory.getLogger(MyRealm.class);
    
        @SuppressWarnings("unchecked")
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
            /**
             *
             * 流程 1.根据用户user->2.获取角色id->3.根据角色id获取权限
             */
            // 01、获取用户登陆ing
            String realName = (String) principals.getPrimaryPrincipal();
            LOGGER.info("realName{}", realName);
            // 02、设置查询条件
            UserInfo info = new UserInfo();
            info.setRealName(realName);
            info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
            // 03、查询对象信息
            UserInfo userInfo = userInfoService.getInfo(info);
            LOGGER.info("admin.id{}", userInfo.getId());
            LOGGER.info("admin.name{}", userInfo.getUserName());
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            // 04、获取用户下的所有角色
            List<RoleInfo> rolelist = roleInfoService.getRoles(userInfo.getId());
            // 获取所有角色的 Id
            List<Long> rolesIds = new ArrayList<Long>();
            for (RoleInfo item : rolelist) {
                rolesIds.add(item.getId());
            }
            // 05、角色下所拥有的所有权限
            List<MenuFunction> listMenus = menuFunctionService.getListMenus(rolesIds);
            // 获取访问的权限
            List<String> patterns = new ArrayList<String>();
            for (MenuFunction item : listMenus) {
                patterns.add(item.getPattern());
            }
            // 06、设置绑定 分类级别关系
            List<MenuFunction> menuFunction = menuFunction(listMenus);
            // 07、去掉空的权限
            List<MenuFunction> notNullMenus = notNull(menuFunction);
            // 08、权限菜单集合保存在Session 回话中
            SecurityUtils.getSubject().getSession().setAttribute("menus", notNullMenus);
            // 09、当前用户所拥有的所有权限保存在 session 会话中进行对比
            SecurityUtils.getSubject().getSession().setAttribute("menusPatterns", patterns);
            // 10、当前登录的用户信息
            SecurityUtils.getSubject().getSession().setAttribute("sessionUser", userInfo);
            // 11、将用户拥有的权限保存在 shiro中 用于后期页面的权限验证
            authorizationInfo.addStringPermissions(
                    (List<String>) SecurityUtils.getSubject().getSession().getAttribute("menusPatterns"));
            return authorizationInfo;
        }
    
        /***
         * 认证方法 验证账号密码
         */
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
            System.out.println("进行验证了");
            // 01、获取登录用户名
            String realName = (String) authenticationToken.getPrincipal();
            // 02、设置条件
            UserInfo info = new UserInfo();
            info.setRealName(realName);
            info.setDelFlag(DeleteStatusEnum.NDEL.getValue());
            // 03、查询对象信息
            UserInfo userInfo = userInfoService.getInfo(info);
            if (userInfo == null) {
                throw new UnknownAccountException();
            }
            // 最后的比对需要交给安全管理器
            // 三个参数进行初步的简单认证信息对象的包装(验证密码)
            SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userInfo.getRealName(), userInfo.getUserPwd(),
                    this.getName());
            return authcInfo;
        }
    
        /***
         * 执行遍历
         * 
         * @param menus
         *            所有权限列表集合
         * @param list
         *            指定角色查询到的 权限Id
         * @return
         */
        @SuppressWarnings("unused")
        private List<MenuFunction> menuFunction(List<MenuFunction> menus) {
            // 中转集合
            List<MenuFunction> functions = null;
            try {
                functions = new ArrayList<MenuFunction>();
                // 循环遍历菜单层级关系
                // 循环遍历
                for (MenuFunction item : menus) {
                    // 获取pid
                    long pid = item.getPid();
                    if (pid == 0) {
                        // 遍历一级分类
                        functions.add(item);
                    } else {
                        for (MenuFunction innerCate : menus) {
                            /***
                             * 外层循环 pid 没有的等于0 的话 获取当前对象的 id 作为一级
                             */
                            Long id = innerCate.getId();
    
                            if (id == pid) {
                                innerCate.getChildren().add(item);
                                break;
                            }
                        }
                    }
                }
    
            } catch (Exception e) {
                LOGGER.error("循环遍历层级关系失败!!!" + e);
            }
            return functions;
        }
    
        /***
         * 去掉空的权限
         * 
         * @param list
         * @return
         */
        private List<MenuFunction> notNull(List<MenuFunction> list) {
            List<MenuFunction> menusList = null;
            try {
                // 去掉空的权限
                menusList = new ArrayList<MenuFunction>();
                for (int i = 0; i < list.size(); i++) {
                    if (list.get(i).getChildren().size() != 0) {
                        menusList.add(list.get(i));
                        notNull(list.get(i).getChildren());
                    }
                }
            } catch (Exception e) {
                LOGGER.error("去除空的权限时意外出错!!!" + e);
            }
            return menusList;
        }
    }

    Controller 关键代码:

    package com.dsj.gdbd.controller.login;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    /***
     * 登陆
     * @author asus
     *
     */
    @Controller
    @RequestMapping("login")
    public class LoginController {
     
        /***
         * 跳转登录页
         * @return
         */
        @RequestMapping("to_login")
        public String login() {
            
            return "login/login";
        }
    }
    package com.dsj.gdbd.controller.home;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("home")
    public class HomeController {
     
        /***
         * 跳转主页面
         * @return
         */
        @RequestMapping("to_index")
        public String login() {
            
            return "home/welcome";
        }
    }

    login.jsp:登录页:(重点关注 form 表单 与 异常处理 )

    <%@ page contentType="text/html;charset=UTF-8"%>
    <%@include file="/WEB-INF/jsp/common/taglibs.jspf"%>
    <html lang="en">
    <head>
    <link rel="stylesheet" href="${ctx}/static/front/css/login/style.css">
    <link rel="stylesheet"
        href="${ctx}/static/front/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="${ctx}/static/front/js/jquery.min.js"></script>
    <script src="${ctx}/static/front/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src='${ctx}/static/front/js/style.js'></script>
    <script type="text/javascript">
        var _ctx = '${ctx}';
    </script>
    <title>登录</title>
    </head>
    <style>
    </style>
    <body>
        <!-- <div class="bj"> -->
        <header>
            <img src="${ctx}/static/front/images/login/logo.png" alt="">
        </header>
        <!-- </div> -->
    
        <div class="city">
            <img src="${ctx}/static/front/images/login/4.png" alt="">
            <div class="denglu">
                <div class="titBian">
                    <span class="tit">用户登录</span>
    
                </div>
                <form id="loginForm" action="${ctx }/login/to_login" method="post">
                    <div class="fengexian"></div>
                    <div class=" alert-danger dengLuTiShi" id="errorDiv">
                        <span class="dengLuTiShiTu glyphicon glyphicon-minus-sign"></span><span
                            id="error" class="cuo">${errormsg }</span>
                    </div>
    
                    <div class="input-group name">
                        <span class="input-group-addon tx1" id="basic-addon1"><img
                            id="tx" class="tupian"
                            src="${ctx}/static/front/images/login/tuyiyi-com-0.png" alt=""></span>
                        <input type="text" id="phone" onclick="phone2()" name="username"
                            class="form-control" autocomplete="off" placeholder="请输入手机号或账号"
                            aria-describedby="basic-addon1"> <span
                            class="input-group-addon cha1" id="cha" onclick="qingkong()">X</span>
                    </div>
                    <div class="input-group password">
                        <span class="input-group-addon tx1" id="basic-addon2"><img
                            src="${ctx}/static/front/images/login/7.png" id="mm"
                            class="tupian" alt=""></span> <input type="password" id="mima"
                            name="password" class="form-control" onclick="mma()"
                            autocomplete="off" placeholder="请输入密码"
                            aria-describedby="basic-addon1">
                    </div>
                    <span class="wangjimima" onclick="wangji()">忘记密码</span>
                    <button id="login_btn" type="button" class="btn btn-primary btnDL">登录</button>
                </form>
                <%
                    //shiro 获取异常,判断异常类型
                    Object errorClass = request.getAttribute("shiroLoginFailure");
                    if ("org.apache.shiro.authc.IncorrectCredentialsException".equals(errorClass)) {
    
                        request.setAttribute("errormsg", "用户名或密码错误");
                    }
                    if ("org.apache.shiro.authc.UnknownAccountException".equals(errorClass)) {
                        request.setAttribute("errormsg", "用户不存在或已禁用");
                    }
                    if ("com.dsj.data.shiro.filter.VerifyCodeException".equals(errorClass)) {
                        request.setAttribute("errormsg", "验证码不正确");
                    }
                %>
    
            </div>
    
        </div>
        <div class="yun">
            <div class="kuanCont">
                <a class="kuan">&nbsp;&nbsp;联系我们xxxxx&nbsp;&nbsp;</a> <a
                    class="kuan kuanLast">&nbsp;&nbsp;北京xxxxx技术服务有限公司&nbsp;&nbsp; </a>
            </div>
        </div>
        <script type="text/javascript">
            $(function() {
                $("#login_btn").off().on("click", function() {
                    $("#loginForm").submit();
                });
                if ('${errormsg }' != '') {
                    var errorDiv = document.getElementById('errorDiv');
                    $("#error").html("${errormsg }");
                    errorDiv.style.visibility = 'visible';
                }
    
            })
    
            $(document).keydown(function(event) {
                if (event.keyCode == 13) { //绑定回车 
                    $('#login_btn').click();
                }
            });
        </script>
        <script src="${ctx }/static/back/login/login.js"></script>
    </body>
    </html>

    其他 相关 Shiro 权限 Demo:案例Demo并不是很完整,你只需要拿走里面你需要的配置就好。

    下载地址一  下载地址二

  • 相关阅读:
    Cannot find class [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter]
    HTTP的长连接和短连接
    Nginx(三)nginx 反向代理
    Nginx(四)nginx 负载均衡
    postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析
    低层次父母,喜欢不停地“讲道理”,而高层次父母,会做2件事
    oracle数据库数据量如何计算,怎么查看oracle数据库数据量大小?
    Git的eclipse插件(下载、抓取、提交、恢复、比较)
    Linux 上 定时备份postgresql 数据库的方法
    Nginx(二)nginx.conf 配置文件
  • 原文地址:https://www.cnblogs.com/mlq2017/p/10126401.html
Copyright © 2020-2023  润新知