happyCode(11core) Shiro 动态权限

建表:一个用户可以有多个角色,一个角色有多个访问权限,有普通请求URL权限,按钮权限,菜单权限(图标,父级菜单)

# 用户表
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`(
    `uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `username` varchar(50) DEFAULT NULL COMMENT '用户名称',
    `fullname` varchar(50) DEFAULT NULL COMMENT '用户昵称',
    `password` varchar(255) DEFAULT NULL COMMENT '密码',
    `salt` varchar(255) DEFAULT NULL COMMENT '密码盐',
    `status` int(1) NOT NULL COMMENT '状态:0可用;1冻结',
    `create_time` datetime DEFAULT NULL COMMENT '创建时间',
    `update_time` datetime DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO `sys_user` (`uid`,`username`,`fullname`,`password`,`salt`,`status`) VALUES ('1', 'root', '超级管理员', '02f7f19c004b7f3369f29b34f868fb4a', '6a6ad5eadcd06d22cab18e31b4d0cdab', 0);

# 角色表
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
    `rid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `rname` varchar(50) DEFAULT NULL COMMENT '角色名称',
    `description` varchar(255) DEFAULT NULL COMMENT '角色描述',
    `status` int(1) NOT NULL COMMENT '状态:0有效;1无效',
    `create_time` datetime DEFAULT NULL COMMENT '创建时间',
    `update_time` datetime DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`rid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# 权限表
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
	`pid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
	`pname` varchar(255) DEFAULT NULL COMMENT '权限名称',
	`description` varchar(255) DEFAULT NULL COMMENT '权限描述',
	`url` varchar(255) DEFAULT NULL COMMENT '权限访问路径',
	`ptype` int(1) NOT NULL COMMENT '类型:0普通权限,1按钮权限,2菜单权限',
	`parent_pid` int(11) COMMENT '上级菜单',
	`innc` varchar(255) DEFAULT NULL COMMENT '图标',
	`status` int(1) NOT NULL COMMENT '状态:0有效;1无效',
	`create_time` datetime DEFAULT NULL COMMENT '创建时间',
    `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  	PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# 用户角色关系表
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role`(
	`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `uid` varchar(20) NOT NULL COMMENT '用户id',
    `rid` varchar(20) NOT NULL COMMENT '角色id',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

# 角色权限关系表
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `rid` varchar(20) NOT NULL COMMENT '角色id',
  `pid` varchar(20) NOT NULL COMMENT '权限id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
package com.oo.core.dao;

import java.util.List;

import org.apache.ibatis.annotations.Select;

import com.oo.comm.MyMapper;
import com.oo.core.entity.SysPermission;

public interface SysPermissionMapper extends MyMapper<SysPermission>{
	@Select("select * from sys_permission")
	List<SysPermission> selectAll();
	@Select("select * from sys_permission as p inner join sys_role_permission as rp on p.pid=rp.pid  where rp.rid = #{rid}")
	List<SysPermission> selectByRid(Long rid);
}
package com.oo.core.dao;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import com.oo.core.entity.SysUser;

public interface SysUserMapper{
	@Select("select uid,username,password,fullname,status,salt,create_time as createTime,update_time as updateTime from sys_user  where username = #{username}")
	@Results({
		@Result(property="uid",column="uid"),
		@Result(property="sysRoleList",column="uid",many=@Many(select="com.oo.core.dao.SysRoleMapper.selectByUid",fetchType=FetchType.LAZY))//在关联查询时,利用延迟加载,先加载主信息。使用关联信息时再去加载关联信息
	})
	public SysUser selectByUsername(String username);
}
mybatis: 
  mapper-locations: classpath:mapper/*.xml
  configuration: 
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #MyBatis 输出SQL日志
    cache-enabled: true

一个用户多个角色,一个角色多个权限,MyBatis对象一对多关系映射,延迟加载

权限配置

package com.oo.config.shiro;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.oo.core.entity.SysPermission;
import com.oo.core.service.impl.SysPermissionService;

/**
 *  用户权限配置类
 * @author LU http://blog.csdn.net/phone13144830339
 * @date 2018年11月10日
 */
@Configuration
public class ShiroConfig {
	@Autowired
	SysPermissionService sysPermissionService;
	/**
	 *    配置过滤器
	 * @param securityManager
	 * @return
	 */
    @Bean("shiroFilter")                                                                                                                                                                                                               
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //定义shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //设置securityManager 安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /*
        Shiro内置的FilterChain,一个URL可以配置多个Filter,使用逗号分隔。当配置多个过滤器时,全部验证通过才视为通过。部分过滤器可以指定参数,如:perms,roles
        anon        org.apache.shiro.web.filter.authc.AnonymousFilter
        authc	    org.apache.shiro.web.filter.authc.FormAuthenticationFilter
        authcBasic	org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
        perms	    org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
        port	    org.apache.shiro.web.filter.authz.PortFilter
        rest	    org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
        roles	    org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
        ssl	        org.apache.shiro.web.filter.authz.SslFilter
        user	    org.apache.shiro.web.filter.authc.UserFilter
        */
        //进行顺序过滤器配置 LinkedHashMap是有序的
        Map<String,String> filterChainMap = new LinkedHashMap<String,String>();
        //资源文件访问配置,anon匿名访问、authc用户认证、roles角色、perms权限
        filterChainMap.put("/css/**","anon");
        filterChainMap.put("/js/**","anon");
        filterChainMap.put("/img/**","anon");
        filterChainMap.put("/login", "anon");
        filterChainMap.put("/logout","logout");
        //动态权限配置
        List<SysPermission> sysPermissionList = sysPermissionService.selectAll();
        for(SysPermission sysPermission:sysPermissionList) {
        	filterChainMap.put(sysPermission.getUrl(), sysPermission.getPname());
        }
        filterChainMap.put("/**","authc");//其它的,要authc:用户认证
        shiroFilterFactoryBean.setLoginUrl("/login.html");//设置用户进行认证跳转的页面
        shiroFilterFactoryBean.setSuccessUrl("/index.html");//设置用户认证成功跳转的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");//设置用户没有权限跳转的页面
        //设置shiroFilterFactoryBean的FilterChainDefinitionMap
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }
  
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        //设置自定义realm
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }
     
    /**
     * 身份认证realm;(这个需要自己写,账号密码校验;用户权限赋予等)
	 * @return
	 */
    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }
  
   /**
	* 凭证匹配器
    * @return
    */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1);//散列的次数,比如散列两次,相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }
}

自定义Relam,用户认证,用户授权(访问需要权限的url时,进行回调)

package com.oo.config.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.oo.core.entity.SysRole;
import com.oo.core.entity.SysUser;
import com.oo.core.service.impl.SysUserService;
 
/**
 *  自定义realm实现认证
 */
public class MyShiroRealm extends AuthorizingRealm {
	@Autowired
	SysUserService sysUserService;
    /**
     * 认证信息(身份验证)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    	UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    	//获取用户的输入的账号Subject login登入时, Token中传递的用户名称参数,UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());//用户名称,用户密吗
    	String username = token.getUsername();
        SysUser user =  sysUserService.selectSysUserByUsername(username);
        //账号不存在
        if (null == user) {
            throw new UnknownAccountException();
        }
        //账号被冻结
        if (user.getStatus()==1) {
            throw new LockedAccountException();
        }
    	SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),ByteSource.Util.bytes(user.getSalt()), getName());
    	return authenticationInfo;
    }
    
    /**
	 * 用户 授权
	 */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    	 SysUser sysUser  = (SysUser)principals.getPrimaryPrincipal();
         sysUser=sysUserService.selectSysUserByUsername(sysUser.getUsername());
    	 System.out.println(sysUser);
         for(SysRole role:sysUser.getSysRoleList()){
             authorizationInfo.addRole(role.getRname());
             /*for(SysPermission p:role.getPermissions()){
                 authorizationInfo.addStringPermission(p.getPermission());
             }*/
         }
         authorizationInfo.addStringPermission("add:user");
         return authorizationInfo;
    }
}

登入访问控制

package com.oo.core.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

import com.oo.core.entity.SysUser;
@Controller
public class LoginController {
	Logger logger = LoggerFactory.getLogger(LoginController.class);
	@PostMapping("/login")
	String login(SysUser user) {
		UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());//用户名称,用户密吗
		String error = null;
		Subject currentUser = SecurityUtils.getSubject();
		try {
			currentUser.login(token);
		} catch (UnknownAccountException e) {
			error = "账号错误";
			e.printStackTrace();
		} catch (IncorrectCredentialsException e) {
			error = "密码错误";
			e.printStackTrace();
		} catch (LockedAccountException e) {
			error ="账号冻结";
			e.printStackTrace();
	    } catch (AuthenticationException e) {
			error = "其他问题";
			e.printStackTrace();
		}
		if(error==null) {
			return "redirect:index.html";
		} else {
			logger.info("登入失败!"+"["+error+"]");
			return "redirect:login.html";
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值