SpringBoot整合Shiro权限框架

Shiro是一个非常不错的权限框架,它提供了登录和权限验证功能,如果想去了解它的话可以去Shiro官网学习  点击打开

1.创建数据库脚本

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for module
-- ----------------------------
DROP TABLE IF EXISTS `module`;
CREATE TABLE `module`  (
  `mid` int(11) NOT NULL AUTO_INCREMENT,
  `mname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`mid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of module
-- ----------------------------
INSERT INTO `module` VALUES (1, 'add');
INSERT INTO `module` VALUES (2, 'delete');
INSERT INTO `module` VALUES (3, 'query');
INSERT INTO `module` VALUES (4, 'update');

-- ----------------------------
-- Table structure for module_role
-- ----------------------------
DROP TABLE IF EXISTS `module_role`;
CREATE TABLE `module_role`  (
  `rid` int(11) NULL DEFAULT NULL,
  `mid` int(11) NULL DEFAULT NULL,
  INDEX `rid`(`rid`) USING BTREE,
  INDEX `mid`(`mid`) USING BTREE,
  CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of module_role
-- ----------------------------
INSERT INTO `module_role` VALUES (1, 1);
INSERT INTO `module_role` VALUES (1, 2);
INSERT INTO `module_role` VALUES (1, 3);
INSERT INTO `module_role` VALUES (1, 4);
INSERT INTO `module_role` VALUES (2, 1);
INSERT INTO `module_role` VALUES (2, 3);

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `rid` int(11) NOT NULL AUTO_INCREMENT,
  `rname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`rid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, 'admin');
INSERT INTO `role` VALUES (2, 'customer');
INSERT INTO `role` VALUES (3, NULL);

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'hlhdidi', '123');
INSERT INTO `user` VALUES (2, 'xyycici', '1992');
INSERT INTO `user` VALUES (3, 'sujin', '123');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (
  `uid` int(11) NULL DEFAULT NULL,
  `rid` int(11) NULL DEFAULT NULL,
  INDEX `u_fk`(`uid`) USING BTREE,
  INDEX `r_fk`(`rid`) USING BTREE,
  CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1);
INSERT INTO `user_role` VALUES (2, 2);
INSERT INTO `user_role` VALUES (3, 3);

SET FOREIGN_KEY_CHECKS = 1;

当新添加一个用户时,只需要配置权限即可,module_role表中已经配置了什么权限拥有什么样的功能

SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid
        inner join role r on r.rid=ur.rid
        inner join module_role mr on mr.rid=r.rid
        inner join module m on mr.mid=m.mid
        WHERE username='hlhdidi'; -- xyycici用户已分配只要两个权限 add和query

2.pom.xml中添加Springboot集成shiro的相关依赖


	
		org.apache.shiro
		shiro-spring
		1.2.5
	
	
		org.apache.shiro
		shiro-ehcache
		1.2.5
	
	
		com.github.theborakompanioni
		thymeleaf-extras-shiro
		1.2.1
	

3.创建实体类

仅列出关键实体类,其他实体类无需改动

用户 

package com.king.s5.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
//用户
public class User implements Serializable{
    private Integer uid;

    private String username;

    private String password;

    private Set roles = new HashSet<>();


    public User(Integer uid, String username, String password) {
        this.uid = uid;
        this.username = username;
        this.password = password;
    }

    public User() {
        super();
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    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 Set getRoles() {
        return roles;
    }

    public void setRoles(Set roles) {
        this.roles = roles;
    }
}

功能 

package com.king.s5.model;

import java.util.HashSet;
import java.util.Set;
//功能
public class Module {
    private Integer mid;

    private String mname;

    private Set roles;

    public Module(Integer mid, String mname) {
        this.mid = mid;
        this.mname = mname;
    }

    public Module() {
        super();
    }

    public Integer getMid() {
        return mid;
    }

    public void setMid(Integer mid) {
        this.mid = mid;
    }

    public String getMname() {
        return mname;
    }

    public void setMname(String mname) {
        this.mname = mname;
    }

    public Set getRoles() {
        return roles;
    }

    public void setRoles(Set roles) {
        this.roles = roles;
    }
}

权限

public class Role {
    private Integer rid;

    private String rname;

    private Set users = new HashSet<>();
    private Set Modules = new HashSet<>();

    public Role(Integer rid, String rname) {
        this.rid = rid;
        this.rname = rname;
    }

    public Role() {
        super();
    }

    public Integer getRid() {
        return rid;
    }

    public void setRid(Integer rid) {
        this.rid = rid;
    }

    public String getRname() {
        return rname;
    }

    public void setRname(String rname) {
        this.rname = rname;
    }

    public Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    }

    public Set getModules() {
        return Modules;
    }

    public void setModules(Set modules) {
        Modules = modules;
    }
}

4.编写持久层mapper.xml 

userMapper.xml,本次只写到mapper层,不做service层(仅列出关键mapper.xml),其他xml无需改变




  
    
      
      
      
    
  
  
    
    
    
    
      
      
      
        
        
      
    
  
  
    uid, username, password
  
  
  
  
    delete from user
    where uid = #{uid,jdbcType=INTEGER}
  
  
    insert into user (uid, username, password
      )
    values (#{uid,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}
      )
  
  
    insert into user
    
      
        uid,
      
      
        username,
      
      
        password,
      
    
    
      
        #{uid,jdbcType=INTEGER},
      
      
        #{username,jdbcType=VARCHAR},
      
      
        #{password,jdbcType=VARCHAR},
      
    
  
  
    update user
    
      
        username = #{username,jdbcType=VARCHAR},
      
      
        password = #{password,jdbcType=VARCHAR},
      
    
    where uid = #{uid,jdbcType=INTEGER}
  
  
    update user
    set username = #{username,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR}
    where uid = #{uid,jdbcType=INTEGER}
  

moduleMapper.xml




  
    
      
      
    
  
  
    mid, mname
  
  
  
    delete from module
    where mid = #{mid,jdbcType=INTEGER}
  
  
    insert into module (mid, mname)
    values (#{mid,jdbcType=INTEGER}, #{mname,jdbcType=VARCHAR})
  
  
    insert into module
    
      
        mid,
      
      
        mname,
      
    
    
      
        #{mid,jdbcType=INTEGER},
      
      
        #{mname,jdbcType=VARCHAR},
      
    
  
  
    update module
    
      
        mname = #{mname,jdbcType=VARCHAR},
      
    
    where mid = #{mid,jdbcType=INTEGER}
  
  
    update module
    set mname = #{mname,jdbcType=VARCHAR}
    where mid = #{mid,jdbcType=INTEGER}
  

5.添加shiro的工具类

认证授权工具类

package com.king.s5.shiro;

import com.king.s5.biz.IUserBiz;
import com.king.s5.mapper.UserMapper;
import com.king.s5.model.Module;
import com.king.s5.model.Role;
import com.king.s5.model.User;
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 org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class AuthRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
        String username = utoken.getUsername();
        User user = userMapper.queryUserName(username);
        //放入shiro.调用CredentialsMatcher检验密码
        return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());
    }
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //获取session中的用户
        User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();
        List permissions=new ArrayList<>();
        Set roles = user.getRoles();
        if(roles.size()>0) {
            for(Role role : roles) {
                Set modules = role.getModules();
                if(modules.size()>0) {
                    for(Module module : modules) {
                        permissions.add(module.getMname());
                    }
                }
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //将权限放入shiro中.
        info.addStringPermissions(permissions);
        return info;
    }
}

权限用户密码校验类

package com.king.s5.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

public class CredentialsMatcher extends SimpleCredentialsMatcher {

    //校验
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;
        //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
        String inPassword = new String(utoken.getPassword());
        //获得数据库中的密码
        String dbPassword=(String) info.getCredentials();
        //进行密码的比对
        return this.equals(inPassword, dbPassword);
    }
}

shiro配置类

package com.king.s5.shiro;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * shiro的配置类
 * @author sujin
 *
 */
@Configuration
public class ShiroConfiguration {
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        //配置登录的url和登录成功的url
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/home");
        //配置访问权限
        LinkedHashMap filterChainDefinitionMap=new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login*", "anon"); //表示可以匿名访问
        filterChainDefinitionMap.put("/loginUser", "anon");
        filterChainDefinitionMap.put("/client/test", "anon");
        filterChainDefinitionMap.put("/assert/test", "anon");//添加白名单
        filterChainDefinitionMap.put("/assert/get", "anon");//添加白名单
        filterChainDefinitionMap.put("/assert/assertQuery", "anon");//添加白名单
        filterChainDefinitionMap.put("/a", "anon");
        filterChainDefinitionMap.put("/book/list", "anon");
        filterChainDefinitionMap.put("/logout*","anon");
        filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
        filterChainDefinitionMap.put("/jsp/login.jsp*","authc");
        filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
        filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
        filterChainDefinitionMap.put("/*.*", "authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }
    //配置核心安全事务管理器
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }
    //配置自定义的权限登录器
    @Bean(name="authRealm")
    public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        AuthRealm authRealm=new AuthRealm();
        authRealm.setCredentialsMatcher(matcher);
        return authRealm;
    }
    //配置自定义的密码比较器
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new CredentialsMatcher();
    }
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }
}

6.控制层controller

package com.king.s5.controller;

import com.king.s5.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login() {
        return "login";
    }

    @RequestMapping("/a")
    public String a() {
        return "a";
    }

    @RequestMapping("/loginUser")
    public String loginUser(String username,String password,HttpSession session) {
        //授权认证
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            //完成登录
            subject.login(usernamePasswordToken);
            //获得用户对象
            User user=(User) subject.getPrincipal();
            //存入session
            session.setAttribute("user", user);
            return "index";
        } catch(Exception e) {
            return "login";//返回登录页面
        }

    }
    @RequestMapping("/logOut")
    public String logOut(HttpSession session) {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
//        session.removeAttribute("user");
        return "login";
    }
}

7.视图层jsp

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>



    登录


欢迎登录!${user.username }



index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>



    登录


欢迎${user.username }光临!请选择你的操作:


  • 增加
  • 删除
  • 修改
  • 查询
点我注销

8.shiro标签的使用

guest标签  验证当前用户是否为“访客”,即未认证(包含未记住)的用户 
user标签 认证通过或已记住的用户
authenticated标签 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在
notAuthenticated标签 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户
principal 标签 输出当前用户信息,通常为登录帐号信息
hasRole标签 验证当前用户是否属于该角色
lacksRole标签 与hasRole标签逻辑相反,当用户不属于该角色时验证通过
hasAnyRole标签 验证当前用户是否属于以下任意一个角色
hasPermission标签 验证当前用户是否拥有指定权限
lacksPermission标签 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过

如果大家有什么问题,可以在下方留言,想要源码的可以到我的资源库下载    点击下载 

 

--------------如果大家喜欢我的博客,可以点击左上角的关注哦。

你可能感兴趣的:(SpringBoot,Spring,Boot整合体系终章)