shiro权限管理实例

1、新建shiro-test工程,选择Spring Web和Thymeleaf依赖
在这里插入图片描述
2、添加相关依赖包

        <!--添加shiro依赖-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!--添加shiro支持thymeleaf标签依赖-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--添加shiro EhCache缓存依赖-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

3、在resources下添加ehcache添加ehcache缓存配置文件ehcache.xml
在这里插入图片描述
配置文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<ehcache>
    <!-- 磙盘的缓存位置-->
    <diskStore path="java.io.tmpdir/ehcache"/>
    <!--默认缓存-->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal = "false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy ="localTempSwap"/>
    </defaultCache>

    <!-- ShiroTest缓存 -->
    <cache name ="ShiroTestCache"
           maxEntriesLocalHeap="1000"
           eternal = "false"
           timeToIdleSeconds="5"
           timeToLiveSeconds="5"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"/>
</ehcache>

4、在static下新建js文件夹,并将md5 js加密算法与 jquery复制到js下
在这里插入图片描述
5、template下添加login.html,noPermission.html,Index.html

                                      <!--login.html-->
<!DOCTYPE html>
<html lang="en" xmlns:th ="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script th:src="@{|/js/jquery-1.8.0.min.js|}"></script>
    <script th:src="@{|/js/jquery.md5.js|}"></script>
    <script>
        //页面加载完毕后将登录按钮单件事件绑定以下方法
        $(function(){
            $("#btnSubmit").bind("click",function() {
                var  md5_password = $.md5($("#password").val());
                console.log(md5_password);
                alert(md5_password);
                $("#md5Password").val(md5_password);
            })
        })
    </script>
</head>
<body>
<form action ="/" method="post">
    <label>用户名</label><input type = "text" id = "userName" name ="userName"><br>
    <label>密码</label><input type ="password" id = "password"><br>
    <input type ="hidden" id = "md5Password" name ="password">
    <input type = "submit" id ="btnSubmit" value ="登录">
    <span style="color:firebrick" th:text="${errMessage}"/>
</form>
</body>
</html>
                        <!--noPermission.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: firebrick">对不起,您没有操作权限</h1>
</body>
</html>
                    <!--index.html-->
<!DOCTYPE html>
<!--添加thymeleaf与shiro命名空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro ="http://www.polix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<shiro:guest>
    您还没有登录
</shiro:guest>
<a th:href = "@{|/user/add|}">添加用户</a>
<a th:href = "@{|/user/update|}">修改用户</a>
<a th:href = "@{|/user/delete|}">删除用户</a>
<!--登录之后才可以查找用户-->
<shiro:authenticated>
    <a th:href = "@{|/user/search|}">查找用户</a>
</shiro:authenticated>
</body>
</html>
</body>
</html>

6、添加controller文件夹,并在其下添加TestController类

package com.example.shirotest.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

@Controller
public class TestController {
    @GetMapping("/index")
    public String index (){
        return "index";
    }
    @GetMapping("/")
    public String toLogin(){
        return "login";
    }
    @PostMapping("/")
    public String login(String userName, String password, Model model){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        /*如果用户没有通过认证,认证用户*/
        if(!subject.isAuthenticated()){
            //创建UsernamePasswordToke对象
            String errMessage;
            UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
            try {
                subject.login(token);
            } catch (UnknownAccountException e) {
                errMessage = "用户名不存在";
                model.addAttribute("errMessage",errMessage);
                return "login";
            } catch (IncorrectCredentialsException e){
                errMessage = "密码不正确";
                model.addAttribute("errMessage",errMessage);
                return "login";
            } catch(LockedAccountException e){
                model.addAttribute("errMessage","您的账号已经被锁定");
                return "login";
            }
            catch (AuthenticationException e){
                model.addAttribute("errMessage","认证失败");
                return "login";
            }
        }

        return "redirect:index";

    }

    @RequiresPermissions(value ={"user:add"})
    @RequestMapping("/user/add")
    @ResponseBody
    public String userAdd(){
        return "userAdd";
    }

    @RequiresPermissions(value={"user:update"})
    @RequestMapping("/user/update")
    @ResponseBody
    public String userUpdate(){
        return "userUpdate";
    }

    @RequiresPermissions(value ={"user:delete"})
    @RequestMapping("/user/delete")
    @ResponseBody
    public String userDelete(){
        return "userDelete";
    }
    @RequestMapping("/user/search")
    @ResponseBody
    public String userSelect(){
        return "userSelect";
    }
    @RequestMapping("/noPermission")
    public String noPermission(){
        return "noPermission";
    }
    //通过@RequiresPermission标识的无权限异常在此处理
    @ExceptionHandler(value={AuthorizationException.class})
    public String permissionError(Throwable throwable){
        return "noPermission";
    }
}

7、添加自定义realm MyRealm继承自AuthorizingRealm

package com.example.shirotest.realm;

import org.apache.shiro.authc.*;
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 java.util.HashSet;
import java.util.Set;

public class MyRealm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Object obj = principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roles = new HashSet<>();
        Set<String> permissions = new HashSet<>();
        //此处应该是根据用户名查询出所有角色与权限
        if(obj.equals("admin")){
            roles.add("admin");
            permissions.add("user:add");
            permissions.add("user:update");
            permissions.add("user:delete");
            permissions.add("user:search");
        }
        info.addRoles(roles);
        info.addStringPermissions(permissions);
        return info;
    }

    //认证账户
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //根据principalCollection参数获得authenticationToken
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        String userName = token.getUsername();
        String password = new String(token.getPassword());

        //此部分应该是查找数据库后根据是否存在用户及用户密码输错次数判断
        if(!"admin".equals(userName) && !"zhangsan".equals(userName) && !"user".equals(userName)){
            throw new UnknownAccountException();
        }else if("zhangsan".equals(userName)){
            throw new LockedAccountException();
        }
        /*
         *参数1:服务器或输入的用户名,参数2:服务器中的密码,参数3,当前rea的名字
         */
        return  new SimpleAuthenticationInfo(userName,"e10adc3949ba59abbe56e057f20f883e",getName());
    }
}

8、添加config文件夹,并添加ShiroConfig配置类

package com.example.shirotest.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.example.shirotest.realm.MyRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
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 java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    //生成MyRealm bean
    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }
    //生成EhCache bean
    @Bean
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream inputStream = null;
        try {
            inputStream = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        CacheManager cacheManager = new CacheManager(inputStream);
        ehCacheManager.setCacheManager(cacheManager);
        return  ehCacheManager;
    }
    //生成SecurityManager bean
    @Bean
    public SecurityManager securityManager(MyRealm myRealm,EhCacheManager ehCacheManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        //securityManager.setCacheManager(ehCacheManager);
        return securityManager;

    }
    //生成ShiroFilterFactoryBean bean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        //创建ShiroFilterFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置SecurityManager对象
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //设置登录页面
        shiroFilterFactoryBean.setLoginUrl("/");
        //设置登录成功后跳转的页面
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //设置没有权限跳转的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noPermission");
        /*
         * 设置页面拦截规则
         */
        Map<String,String> filterChainMap = new LinkedHashMap<>();
        //配置登陆请求不需要认证 anon表示某个请求不需要认证
        filterChainMap.put("/","anon");
        filterChainMap.put("/noPermission","anon");
        //配置登出的请求,登出后会清空当前用户的内存
        filterChainMap.put("/logout","logout");
        //配置一个admin开头的所有请求需要登录 authc表示需要登录认证
        filterChainMap.put("/user/add","authc,roles[admin]");
        //配置一个user开头的所有请求需要登录 authc表示需要登录认证
        filterChainMap.put("/user/**","authc");
        filterChainMap.put("/js/**","anon");
        //配置剩余的所有请求全部需要进行登录认证(注意:这个必须写在最后面,否则其后的配置不管用),可选配置
        filterChainMap.put("/**","authc");
        //设置权限拦截规则
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }
    //开启shiro注解支持,不开启controller中的@RequiresPermissions无效
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    //开启AOP的支持,不开启controller中的@RequiresPermissions无效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    //配置shiro与thymeleaf的集成
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值