利用shiro实现权限的动态控制

使用shiro对登陆进行权限验证,以及实现权限的动态管理。

数据库表

利用shiro实现权限的动态控制_第1张图片

利用shiro实现权限的动态控制_第2张图片

shiro配置文件

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                        http://www.springframework.org/schema/context    
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                        http://www.springframework.org/schema/mvc    
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                        http://www.springframework.org/schema/util    
                        http://www.springframework.org/schema/util/spring-util-3.2.xsd">

    
    
      
   

    
    
        
        
    


    
    
    
    
        
    


    
    
        
        
        
        
        
        
        
        
        
        
            
                /index.jsp=anon
                /user/update!initAuth=anon
                /baseUtils/update!changePermissions=anon
                /**=authc
           

        

    

    


jdbc配置文件

mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/test
mysql.username=root
mysql.password=123456
#\u5B9A\u4E49\u521D\u59CB\u8FDE\u63A5\u6570  
mysql.initialSize=0
#\u5B9A\u4E49\u6700\u5927\u8FDE\u63A5\u6570  
mysql.maxActive=20
#\u5B9A\u4E49\u6700\u5927\u7A7A\u95F2  
mysql.maxIdle=20
#\u5B9A\u4E49\u6700\u5C0F\u7A7A\u95F2  
mysql.minIdle=1
#\u5B9A\u4E49\u6700\u957F\u7B49\u5F85\u65F6\u95F4  
mysql.maxWait=60000



redis.pool.maxActive=8
redis.pool.maxIdle=8
redis.pool.maxWaitTime=3000
redis.pool.testOnBorrow=false
redis.host.ip=localhost
redis.host.port=6379
shiro.session.timeout=10000
redis.pass=admin


mybatis配置文件


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                            http://www.springframework.org/schema/context    
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                            http://www.springframework.org/schema/mvc    
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
    
    
        
    

    
             destroy-method="close">
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    


    
    
        
        
        
    


    
    
        
        
    


    
    
        
    

      
   
    
 


springMVC配置文件


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                        http://www.springframework.org/schema/context    
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                        http://www.springframework.org/schema/mvc    
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">          
                        
     
                     
                        
    
    
                     expression="org.springframework.stereotype.Controller" />
                     expression="org.springframework.stereotype.Service" />
    

    
    
    
             class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        
            
                text/html;charset=UTF-8
            

        

    

    
             class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        
            
                
            

        

    
    
             class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        
        
    

    
             class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        
        
        
        
        
        
    



spring配置文件


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd    
                        http://www.springframework.org/schema/context    
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd    
                        http://www.springframework.org/schema/mvc    
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
    
    
      
      
      
      



dao层

package com.cn.hnust.dao;

import java.util.List;

import com.cn.hnust.pojo.UrlFilter;

public interface UrlFilterMapper {

    List selectAll();
    
    void insertPermissions(UrlFilter urlFilter);
}


 
 
 
     
        
         
         
         
       
         
   
 
   
    id,url,name,roles,permissions,sort,available
 
 
   
 
      INSERT INTO t_url_permissions(url,name,roles,permissions,sort,available)
      VALUES(#{url,jdbcType=VARCHAR},#{name,jdbcType=VARCHAR},#{roles,jdbcType=VARCHAR},
              #{permissions,jdbcType=VARCHAR},
              #{sort,jdbcType=INTEGER},#{available,jdbcType=VARCHAR})
 


package com.cn.hnust.dao;

import com.cn.hnust.pojo.User;

public interface IUserDao {
    
    User selectByPrimaryKey(Integer userId);
    
    User selectByUsername(String name);
}
 
 
 
     
        
         
       
         
   
 
   
    id,user_name, password  ,age
 
 
   
 


POJO实体类

package com.cn.hnust.pojo;

import java.io.Serializable;

public class UrlFilter implements Serializable{
    
    /**
     *
     */
    private static final long serialVersionUID = 2725744448169512486L;
    
    private Long id;
    //地址描述
    private String name;
    //地址
    private String url;
    //所需角色
    private String roles;
    //所需权限
    private String permissions;
    //是否启用
    private String available;
    //排序
    private String sort;
    
    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getRoles() {
        return roles;
    }
    public void setRoles(String roles) {
        this.roles = roles;
    }
    public String getPermissions() {
        return permissions;
    }
    public void setPermissions(String permissions) {
        this.permissions = permissions;
    }
    public String getAvailable() {
        return available;
    }
    public void setAvailable(String available) {
        this.available = available;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getSort() {
        return sort;
    }
    public void setSort(String sort) {
        this.sort = sort;
    }
}

package com.cn.hnust.pojo;

public class User {

    private Integer id;
    private String userName;
    private String password;
    private Integer age;
    public Integer getId() {
        return id;
    }
    public void setId(Integer 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 Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    
    
}

service层

package com.cn.hnust.service.impl;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cn.hnust.dao.UrlFilterMapper;
import com.cn.hnust.pojo.UrlFilter;
import com.cn.hnust.service.UrlFilterService;


@Service
public class UrlFilterServiceImpl implements UrlFilterService {
    private static final String CRLF = "\r\n";
    @Autowired
    private UrlFilterMapper urlFilterMapper;

    @Override
    public String selectAllPermissions() {
        StringBuilder sb = new StringBuilder();
        List urls = urlFilterMapper.selectAll();
        for (UrlFilter urlFilter : urls) {
            sb.append(urlFilter.getUrl()).append(" == ").append(urlFilter.getPermissions()).append(CRLF);
        }
        return sb.toString();
    }

    @Override
    public void insertPermissions(UrlFilter urlFilter) {
        urlFilterMapper.insertPermissions(urlFilter);
    }

}

package com.cn.hnust.service.impl;  
 
import javax.annotation.Resource;  
 
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.UrlFilenameViewController;

import com.cn.hnust.dao.IUserDao;  
import com.cn.hnust.pojo.User;  
import com.cn.hnust.service.IUserService;  
 
@Service("userService")  
public class UserServiceImpl implements IUserService {  
    @Resource  
    private IUserDao userDao;

    public User getUserById(Integer userId) {
        // TODO Auto-generated method stub
        return this.userDao.selectByPrimaryKey(userId);
    }

    @Override
    public User getUserByName(User user) {
        if(null == user || null == user.getUserName())
            return null;
            
        return userDao.selectByUsername(user.getUserName());
    }  
    
 
}
controller层

package com.cn.hnust.controller;  

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.cn.hnust.pojo.User;
import com.cn.hnust.service.IUserService;
import com.cn.hnust.utils.BOSRealm;
import com.cn.hnust.utils.ShiroManager;  

@Controller  
@RequestMapping("/user")  
public class UserController {  
    @Resource  
    private IUserService userService;  
    @Autowired
    private ShiroManager shiroManager;
      
    //@RequiresPermissions("sys")
    @RequestMapping("/showUser")  
    public String toIndex(HttpServletRequest request,Model model){  
        Integer userId = Integer.parseInt(request.getParameter("id"));  
        User user = this.userService.getUserById(userId);  
        model.addAttribute("user", user);  
        return "showUser";  
    }
    
    @RequestMapping("/login")  
    public String toLogin(HttpServletRequest request,Model model){  
        Subject subject = SecurityUtils.getSubject();
        String password = request.getParameter("password");
        String username = request.getParameter("username");
        
        System.out.println(username+"<----->"+password);
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try{
            subject.login(token);
        }catch(UnknownAccountException ue){
            System.out.println("Exception 用户不存在");
        }catch(IncorrectCredentialsException ie){
            System.out.println("Exception 密码错误");
        }
        User user = (User) subject.getPrincipal();
        
        model.addAttribute("user", user);
        return "showUser";  
    }
    
    /**
     * 用户登出
     */  
    @RequestMapping("/logout")  
    public String logout(HttpServletRequest request){  
         SecurityUtils.getSubject().logout();  
         return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";  
    }
    
    
    /**
     * 清除权限
     */
    public void clearAuthz(){
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        BOSRealm realm  = (BOSRealm) rsm.getRealms().iterator().next();
        realm.clearAuthz();
    }
    
    @RequestMapping("/update!initAuth")  
    public String initAuth(){
        shiroManager.reCreateFilterChains();
        return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";  
    }

package com.cn.hnust.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.cn.hnust.pojo.UrlFilter;
import com.cn.hnust.service.impl.UrlFilterServiceImpl;
import com.cn.hnust.utils.ShiroManager;

@Controller
@RequestMapping("/baseUtils")
public class BaseUtilController {
    @Autowired
    private UrlFilterServiceImpl urlFilterServiceImpl;
    @Autowired
    private ShiroManager shiroManager;

    @RequestMapping("/update!changePermissions")
    public String toChangeFilterChain(){
        String filterChains = urlFilterServiceImpl.selectAllPermissions();
        shiroManager.sqlCreateFilterChains(filterChains);
        return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";  
    }
    
    
    @RequestMapping("/insert!addPermissions")
    public String addFilterChain(UrlFilter urlFilter){
        urlFilterServiceImpl.insertPermissions(urlFilter);
        String filterChains = urlFilterServiceImpl.selectAllPermissions();
        System.out.println("重新加载权限:\n"+filterChains);
        shiroManager.sqlCreateFilterChains(filterChains);
        return "addPermissions";  
    }
    
    
    @RequestMapping("/select!showPage")
    public String showPage(String pageName){
        return pageName;  
    }
}

utils工具类

package com.cn.hnust.utils;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.cn.hnust.pojo.User;
import com.cn.hnust.service.IUserService;

public class BOSRealm extends AuthorizingRealm{
    @Autowired
    private IUserService userService;  
    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principla) {
        //获取当前登陆的用户名
        SimpleAuthorizationInfo inf = new SimpleAuthorizationInfo();
        User principlaUser = (User)super.getAvailablePrincipal(principla);  
        
        if(null != principlaUser){
            System.out.println("当前登陆的用户--->"+principlaUser.getUserName());
            User user = userService.getUserByName(principlaUser);
            
            Set roles = new HashSet<>();
            roles.add(user.getUserName());
            Set perms = new HashSet<>();
            perms.add("sys");
            perms.add("userAdd");
            
            inf.setRoles(roles);
            inf.setStringPermissions(perms);
        }
        
        
        return inf;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        
        UsernamePasswordToken token = (UsernamePasswordToken) auth;
        System.out.println("进行登陆校验的用户="+token.getUsername());
        User user = new User();
        user.setUserName(token.getUsername());
        
        user = userService.getUserByName(user);
        if(null == user)
            return null;
        
        return new SimpleAuthenticationInfo(user,(user == null? null :user.getPassword()),this.getClass().getSimpleName());
    }
    
    
    public void clearAuthz(){
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

}

package com.cn.hnust.utils;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import com.cn.hnust.service.impl.UrlFilterServiceImpl;

/**
 * 动态加载权限 Service
 */
@Service
public class ShiroManager{
    
    // 注意/r/n前不能有空格
    private static final String CRLF = "\r\n";
    @Autowired
    private ShiroFilterFactoryBean shiroFilterFactoryBean;
    
    public String loadFilterChainDefinitions() {
        
        StringBuffer sb = new StringBuffer();
        sb.append(getFixedAuthRule());//固定权限,采用读取配置文件
        System.out.println(sb.toString());
        return sb.toString();
    }
    
    /**
     * 从配置文件获取固定权限验证规则串
     */
    private String getFixedAuthRule(){
        String fileName = "shiro_base_auth.ini";
        ClassPathResource cp = new ClassPathResource(fileName);
        INI4j ini = null;
        try {
            ini = new INI4j(cp.getFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
        String section = "base_auth";
        Set keys = ini.get(section).keySet();
        StringBuffer sb = new StringBuffer();
        for (String key : keys) {
            String value = ini.get(section, key);
            sb.append(key).append(" = ").append(value).append(CRLF);
        }
        
        return sb.toString();
    }
    
    // 此方法加同步锁
    public synchronized void reCreateFilterChains() {
        AbstractShiroFilter shiroFilter = null;
        try {
            shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
        } catch (Exception e) {
            throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
        }
        PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
        DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
        // 清空老的权限控制
        manager.getFilterChains().clear();
        shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
        shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());
        // 重新构建生成
        Map chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
        
        for (Map.Entry entry : chains.entrySet()) {
            String url = entry.getKey();
            String chainDefinition = entry.getValue().trim().replace(" ", "");
            
            manager.createChain(url, chainDefinition);
        }
    }
    
    
    public synchronized void sqlCreateFilterChains(String filterChains) {
        AbstractShiroFilter shiroFilter = null;
        try {
            shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
        } catch (Exception e) {
            throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
        }
        PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
        DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
        // 清空老的权限控制
        manager.getFilterChains().clear();
        shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
        //String filterChains = urlFilterService.selectAllPermissions();
        shiroFilterFactoryBean.setFilterChainDefinitions(filterChains);
        // 重新构建生成
        Map chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
        
        for (Map.Entry entry : chains.entrySet()) {
            String url = entry.getKey();
            String chainDefinition = entry.getValue().trim().replace(" ", "");
            
            manager.createChain(url, chainDefinition);
        }
    }
    
    
    public void setShiroFilterFactoryBean(ShiroFilterFactoryBean shiroFilterFactoryBean) {
        this.shiroFilterFactoryBean = shiroFilterFactoryBean;
    }
}

package com.cn.hnust.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.core.io.ClassPathResource;
/**
 * 有序读取 ini配置文件
 *
 */
public class INI4j {
    
    /**
     * 用linked hash map 来保持有序的读取
     *
     */
    final LinkedHashMap>  coreMap = new LinkedHashMap>();
    /**
     * 当前Section的引用
     */
    String currentSection = null;
     
    /**
     * 读取
     * @param file 文件
     * @throws FileNotFoundException
     */
    public INI4j(File file) throws FileNotFoundException {
        this.init(new BufferedReader(new FileReader(file)));
    }
    /***
     * 重载读取
     * @param path 给文件路径
     * @throws FileNotFoundException
     */
    public INI4j(String path) throws FileNotFoundException {
        this.init(new BufferedReader(new FileReader(path)));
    }
    /***
     * 重载读取
     * @param source ClassPathResource 文件,如果文件在resource 里,那么直接 new ClassPathResource("file name");
     * @throws IOException
     */
    public INI4j(ClassPathResource source) throws IOException {
        this(source.getFile());
    }

    void init(BufferedReader bufferedReader){
        try {
            read(bufferedReader);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("IO Exception:" + e);
        }
    }
    /**
     * 读取文件
     * @param reader
     * @throws IOException
     */
    void read(BufferedReader reader) throws IOException {
        String line = null;
        while((line=reader.readLine())!=null) {
            parseLine(line);
        }
    }
     
    /**
     * 转换
     * @param line
     */
    void parseLine(String line) {
        line = line.trim();
        // 此部分为注释
        if(line.matches("^\\#.*$")) {
            return;
        }else if (line.matches("^\\[\\S+\\]$")) {
            // section
            String section = line.replaceFirst("^\\[(\\S+)\\]$","$1");
            addSection(section);
        }else if (line.matches("^\\S+=.*$")) {
            // key ,value
            int i = line.indexOf("=");
            String key = line.substring(0, i).trim();
            String value =line.substring(i + 1).trim();
            addKeyValue(currentSection,key,value);
        }
    }


    /**
     * 增加新的Key和Value
     * @param currentSection
     * @param key
     * @param value
     */
    void addKeyValue(String currentSection,String key, String value) {
        if(!coreMap.containsKey(currentSection)) {
            return;
        }
        Map childMap = coreMap.get(currentSection);
        childMap.put(key, value);
    }


    /**
     * 增加Section
     * @param section
     */
    void addSection(String section) {
        if (!coreMap.containsKey(section)) {
            currentSection = section;
            LinkedHashMap childMap = new LinkedHashMap();
            coreMap.put(section, childMap);
        }
    }
     
    /**
     * 获取配置文件指定Section和指定子键的值
     * @param section
     * @param key
     * @return
     */
    public String get(String section,String key){
        if(coreMap.containsKey(section)) {
            return  get(section).containsKey(key) ?  get(section).get(key): null;
        }
        return null;
    }
     
     
     
    /**
     * 获取配置文件指定Section的子键和值
     * @param section
     * @return
     */
    public Map get(String section){
        return  coreMap.containsKey(section) ? coreMap.get(section) : null;
    }
     
    /**
     * 获取这个配置文件的节点和值
     * @return
     */
    public LinkedHashMap> get(){
        return coreMap;
    }
     
}

工程文件位置

利用shiro实现权限的动态控制_第3张图片

你可能感兴趣的:(shiro,java,spring,Mybatis)