博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
项目实录之Shiro的使用
阅读量:6495 次
发布时间:2019-06-24

本文共 15316 字,大约阅读时间需要 51 分钟。

  hot3.png

阅读本文之前建议先阅读如下两篇文章

一、添加相关Jar包
    

在项目pom.xml添如下依赖:

     

            
taglibs
            
standard
            
1.1.2
            
jar
        
        
            
                
org.apache.shiro
                
shiro-core
                
${shiro.version}
            
            
                
org.apache.shiro
                
shiro-spring
                
${shiro.version}
            
            
                
org.apache.shiro
                
shiro-web
                
${shiro.version}
            
            
                
org.apache.shiro
                
shiro-ehcache
                
${shiro.version}
            
            

 

二、数据库表与数据

我们需要3个表,user表示用户,会初始化多个不同权限的用户;menu表示菜单,不同用户拥有不同的菜单;user_menu是用户与菜单的对照表,该用户拥有哪些菜单会在这里标记。实际开发者一般基于角色进行权限管理,为了方便起见,本示例直接基于用户了。

 

CREATE TABLE `user` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `username` varchar(20) NOT NULL,  `password` varchar(20) NOT NULL,  PRIMARY KEY (`id`,`username`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8CREATE TABLE `menu` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `name` varchar(20) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8CREATE TABLE `user_menu` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `user_id` bigint(20) NOT NULL,  `menu_id` bigint(20) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8INSERT INTO USER (id,username,PASSWORD) VALUES (1,'jobs','qwe123')INSERT INTO USER (id,username,PASSWORD) VALUES (2,'gates','888888')INSERT INTO menu (id,NAME) VALUES (1,'菜单一')INSERT INTO menu (id,NAME) VALUES (2,'菜单二')INSERT INTO menu (id,NAME) VALUES (3,'菜单三')INSERT INTO menu (id,NAME) VALUES (4,'菜单四')INSERT INTO menu (id,NAME) VALUES (5,'菜单五')INSERT INTO user_menu (id,user_id,menu_id) VALUES (1,1,1)INSERT INTO user_menu (id,user_id,menu_id) VALUES (2,1,2)INSERT INTO user_menu (id,user_id,menu_id) VALUES (3,1,3)INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,3)INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,4)INSERT INTO user_menu (id,user_id,menu_id) VALUES (4,2,5)

 

我们有jobs和gates两个用户,有菜单一、菜单二、菜单三、菜单四和菜单五五个菜单。jobs拥有菜单一、菜单二和菜单三,gates拥有菜单三、菜单四和菜单五。

三、编写相关代码
1、在dao层新建wang.wangci.bottae.dao.entity.Menu类
  

package wang.wangci.bottae.dao.entity;public class Menu {    private long id;    private String name;    public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }        }

 

2、修改dao层的User类

 

package wang.wangci.bottae.dao.entity;import java.util.ArrayList;import java.util.List;public class User {    private long id;    private String username;    private String password;    private List
 menuList= new ArrayList
();    public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public List
 getMenuList() {        return menuList;    }    public void setMenuList(List
 menuList) {        this.menuList = menuList;    }    }

 

3、在dao层新建 wang.wangci.bottae.dao.entity.UserMenu类

 

package wang.wangci.bottae.dao.entity;public class UserMenu {    private long id;    private long userId;    private long menuId;    public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public long getUserId() {        return userId;    }    public void setUserId(long userId) {        this.userId = userId;    }    public long getMenuId() {        return menuId;    }    public void setMenuId(long menuId) {        this.menuId = menuId;    }    }

 

4、在dao层新建wang.wangci.bottae.dao.mapper.MenuMapper

 

package wang.wangci.bottae.dao.mapper;import java.util.List;import org.apache.ibatis.annotations.Param;import wang.wangci.bottae.dao.entity.Menu;public interface MenuMapper {    public List
 selectsByUserId(@Param("userId")long userId);}

 

4、修改UserMapper接口

 

package wang.wangci.bottae.dao.mapper;import java.util.List;public interface UserMapper {    public List
 selects();        public User selectById(@Param("id")long id);        public User selectByName(@Param("name")String name); }

 

5、修改UserMapper.xml

 

  
            
        SELECT *    FROM user        
        SELECT *    FROM user WHERE id=#{id}            
        SELECT *    FROM user WHERE username=#{name}    

 

6、新增MenuMapper.xml
    

 

  
            
        SELECT         m.id,        m.name        FROM         menu m,        user_menu u        WHERE m.id = u.menu_id AND u.user_id=#{userId}    

 

7、service层修改UserService接口

 

package wang.wangci.bottae.service;import java.util.List;import wang.wangci.bottae.dao.entity.User;public interface UserService {    public List
 finds();        public User findById(long id);        public User findByName(String name);} 8、service层修改UserServiceImpl类 package wang.wangci.bottae.service.impl;import java.util.List;@Componentpublic class UserServiceImpl implements UserService {        @Resource    private UserMapper userMapper;    @Override    public List
 finds() {        return userMapper.selects();    }    @Override    public User findById(long id) {        return userMapper.selectById(id);    }    @Override    public User findByName(String name) {        return userMapper.selectByName(name);    }}

 

9、service层新增MenuService接口

 

package wang.wangci.bottae.service;import java.util.List;import wang.wangci.bottae.dao.entity.Menu;public interface MenuService {    public List
 findsByUserId(long userId);}

 

10、service新增MenuServiceImpl实现类

 

package wang.wangci.bottae.service.impl;import java.util.List;import javax.annotation.Resource;import org.springframework.stereotype.Component;import wang.wangci.bottae.dao.entity.Menu;import wang.wangci.bottae.dao.mapper.MenuMapper;import wang.wangci.bottae.service.MenuService;@Componentpublic class MenuServiceImpl implements MenuService{        @Resource    private MenuMapper menuMapper;    @Override    public List
 findsByUserId(long userId) {        return menuMapper.selectsByUserId(userId);    }}

 

11、web层新建LoginController类

  注意:示例代码并不严谨,如需在实际开发中使用,请进行各种异常处理。

 

package wang.wangci.bottae.web.controllers;import java.util.List;@Controllerpublic class LoginController {        @Resource    private UserService userService;    @Resource    private MenuService menuService;        @RequestMapping("/")    public String index(String passwd,HttpServletRequest request, HttpServletResponse response,ModelMap model){        String username = (String)request.getSession().getAttribute("username");        User user = userService.findByName(username);        if(user!=null){            List
 menus = menuService.findsByUserId(user.getId());            model.addAttribute("menus", menus);        }        return "index";    }        @RequestMapping(value = "/login", method = {RequestMethod.GET,RequestMethod.POST})    public String login(@RequestParam(value="username",defaultValue="",required=false)String username,            @RequestParam(value="passwd",defaultValue="",required=false)String passwd,            HttpServletRequest request, HttpServletResponse response, ModelMap model)throws Exception {                UsernamePasswordToken token = new UsernamePasswordToken(username,passwd);        Subject subject = SecurityUtils.getSubject();        try {            subject.login(token);        }catch (UnknownAccountException uae) {            model.addAttribute("message", "帐号不存在,请重新登录");        }catch (IncorrectCredentialsException ice) {            model.addAttribute("message", "密码错误,请重新登录");        } catch (DisabledAccountException e) {            model.addAttribute("message", "帐号状态异常,禁止登录,请联系系统管理员!");        }                if(subject.isAuthenticated()){            HttpSession session = request.getSession();            session.setAttribute("username", username);            return "redirect:/";        }else{            token.clear();        }        return "login";            }        @RequestMapping("/logout")    public String logout(HttpServletRequest request,HttpServletResponse response,ModelMap model){        SecurityUtils.getSubject().logout();        return "redirect:/login";    }}

 

 12、web层新建HasAnyPermissionsTag类

 

package wang.wangci.bottae.web.security;import org.apache.shiro.subject.Subject;public class HasAnyPermissionsTag extends PermissionTag{    private static final long serialVersionUID = 1L;    private static final String PERMISSION_NAMES_DELIMETER = ",";    @Override    protected boolean showTagBody(String permissionNames) {        boolean hasAnyPermission = false;        Subject subject = getSubject();        if (subject != null) {            for (String permission : permissionNames                    .split(PERMISSION_NAMES_DELIMETER)) {                if (subject.isPermitted(permission.trim())) {                    hasAnyPermission = true;                    break;                }            }        }        return hasAnyPermission;    }}

 

13、web层新建Principal类

 

package wang.wangci.bottae.web.security;import java.io.Serializable;public class Principal implements Serializable{    private static final long serialVersionUID = 1L;        private long id; // 编号    private String name; // 姓名        public Principal(User user) {        this.id = user.getId();        this.name = user.getUsername();    }    public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }            }

 

14、web层新建SystemAuthorizingRealm类

 

package wang.wangci.bottae.web.security;import java.util.List;public class SystemAuthorizingRealm extends AuthorizingRealm {    private static final Logger logger = LoggerFactory            .getLogger(SystemAuthorizingRealm.class);    @Resource    private UserService userService;    @Resource    private MenuService menuService;    /**     * 认证回调函数, 登录时调用     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(            AuthenticationToken authcToken) {        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;        // 校验用户名密码        User user = null;        try {            user = userService.findByName(token.getUsername());        } catch (Exception e) {            e.printStackTrace();        }        if (user != null) {                        return new SimpleAuthenticationInfo(new Principal(user),                    user.getPassword(), getName());        } else {            return null;        }    }    /**     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(            PrincipalCollection principals) {        Principal principal = (Principal) getAvailablePrincipal(principals);        User user = null;        try {            user = userService.findByName(principal.getName());        } catch (Exception e) {            logger.info("查询登录用户出错了",e);        }        if (user != null) {            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();            //是否系统默认高级用户            List
 list = menuService.findsByUserId(user.getId());                        for (Menu menu : list) {                    // 添加基于Permission的权限信息                    info.addStringPermission(menu.getName());            }            // 添加用户权限            info.addStringPermission("user");            // 添加用户角色信息            return info;        } else {            return null;        }    }}

 

15、在resources/context下新建context-shiro.xml文件

 

    
Shiro安全配置
        
    
            
    
        
        
        
        
        
            
                /login = anon                /logout = logout                /static/** = anon                /** = authc            
                
    
        
        
            
    
        
        
                
    
        
    
        
        
        
    

  16、在WEB-INF下面新建目录tlds,在tlds目录下新建文件shiros-ext.tld

 

    
1.1.2
    
1.2
    
Apache Shiro
    
http://shiro.apache.org/tagss
    
Apache Shiro JSP Tag Library extends the hasAnyPermissions        tag.
    
        
hasAnyPermissions
        
wang.wangci.bottae.web.security.HasAnyPermissionsTag
        
JSP
        
Displays body content only if the current user has one of            the specified permissions from a            comma-separated list of permission            names.        
        
            
name
            
true
            
true
        
    

 17、在views目录西新建include文件夹,在include下新建taglib.jsp

 

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%><%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%><%@ taglib prefix="shiro-ext" uri="/WEB-INF/tlds/shiros-ext.tld"%>

 18、在views下新建login.jsp文件

 

<%@ page language="java" pageEncoding="UTF-8"%>
UUID    
        用戶名:
        密碼:
                
    

 19、在views目录下新建index.jsp文件

 

<%@ page language="java" pageEncoding="UTF-8"%><%@ include file="/WEB-INF/views/include/taglib.jsp"%>
UUID你好,${username},你有下面這些權限!
        
            菜单一
                
            菜单二
                
            菜单三
                
            菜单四
                
            菜单五
                        
退出登录

 

20、在web.xml中增加一段拦截配置

       

  
            
          
shiroFilter
          
org.springframework.web.filter.DelegatingFilterProxy
      
      
          
shiroFilter
          
/*
          
REQUEST
          
FORWARD
      

 

 四、运行测试

编译运行起服务。
浏览器输入:localhost:7777,都会被拦截到登录页面。在登录页输入jobs密码qwe123,登录,如果显示jobs拥有菜单一、菜单二、菜单三,说明成功了,点击退出登录,
使用gates/888888登录,如果显示拥有菜单三、菜单四、菜单五说明成功了。 

本文源码:

 访问密码 0385

进入 查看原文

转载于:https://my.oschina.net/funga/blog/485093

你可能感兴趣的文章
我爱我家-北京-mysql
查看>>
win32 进程崩溃时禁止弹出错误对话框
查看>>
FZU 2110 Star 数学
查看>>
POJ 2886Who Gets the Most Candies?(线段树)
查看>>
【Java拾遗】Java transient关键字
查看>>
java批量生成excel文件
查看>>
python机器学习入门(Day3:Pandas)
查看>>
Cassandra操作入门
查看>>
salt 使用state文件来配置zabbix客户端文件
查看>>
求逆序对
查看>>
巴西法律和税收报告以及其他法律要求》》》本质上是一种税务监控手段;
查看>>
docker 命令汇总2
查看>>
MariaDB下载
查看>>
mysql的使用
查看>>
基于python的一个运维自动化的项目(进度更新)【已开源】
查看>>
职场思想分享005 | 别让背后抱怨说别人坏话成为聊天习惯
查看>>
《跟菜鸟学Cisco UC部署实战》-第 1 章 规划-课件(一共12章,免费)
查看>>
Forefront_TMG_2010-TMG发布Web服务器
查看>>
精品德国软件 UltraShredder 文件粉碎机
查看>>
常回“家”看看
查看>>