• SpringBoot集成Shiro


    Shiro是一个安全框架,控制登陆,角色权限管理(身份认证、授权、回话管理、加密)

    Shiro不会去维护用户,维护权限;这些需要通过realm让开发人员自己注入

    1、在pom.xml中引入shiro的jar包

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.4.0</version>
    </dependency>

    2、在srcmain esources下创建ehcache-shiro.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache updateCheck="false" name="cacheManagerConfigFile">
        <defaultCache maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU"/>
        <cache name="shiro-activeSessionCache"
        eternal="false"
        maxElementsInMemory="10000"
        overflowToDisk="false"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"/>
    </ehcache>

    3、创建User类

    package com.cppdy.entity;
    
    public class User {
    
        private int id;
        private String username;
        private String password;
        private int roleid;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public int getRoleid() {
            return roleid;
        }
    
        public void setRoleid(int roleid) {
            this.roleid = roleid;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
    }

    4、创建Role类

    package com.cppdy.entity;
    
    public class Role {
    
        private int id;
        private String rolename;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getRolename() {
            return rolename;
        }
    
        public void setRolename(String rolename) {
            this.rolename = rolename;
        }
    
    }

    5、创建Permission类

    package com.cppdy.entity;
    
    public class Permission {
    
        private int id;
        private String pername;
        private int roleid;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getPername() {
            return pername;
        }
    
        public void setPername(String pername) {
            this.pername = pername;
        }
    
        public int getRoleid() {
            return roleid;
        }
    
        public void setRoleid(int roleid) {
            this.roleid = roleid;
        }
    
    }

    6、创建UserMapper接口

    package com.cppdy.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    
    import com.baomidou.mybatisplus.mapper.BaseMapper;
    import com.cppdy.entity.User;
    
    @Mapper
    public interface UserMapper extends BaseMapper<User>{
    
    }

    7、创建RoleMapper接口

    package com.cppdy.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    
    import com.baomidou.mybatisplus.mapper.BaseMapper;
    import com.cppdy.entity.Role;
    
    @Mapper
    public interface RoleMapper extends BaseMapper<Role>{
    
    }

    8、创建PermissionMapper接口

    package com.cppdy.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    
    import com.baomidou.mybatisplus.mapper.BaseMapper;
    import com.cppdy.entity.Permission;
    
    @Mapper
    public interface PermissionMapper extends BaseMapper<Permission>{
    
    }

    9、创建UserService接口

    package com.cppdy.service;
    
    import com.cppdy.entity.User;
    
    public interface UserService {
    
        public void update(String username, int id);
    
        public User selectUserByUsername(String username);
    
    }

    10、创建UserServiceImpl接口实现类

    package com.cppdy.service.impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.baomidou.mybatisplus.mapper.EntityWrapper;
    import com.baomidou.mybatisplus.mapper.Wrapper;
    import com.cppdy.entity.User;
    import com.cppdy.mapper.UserMapper;
    import com.cppdy.service.UserService;
    
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        // 开启事务管理
        @Transactional
        public void update(String username, int id) {
    
            User user = userMapper.selectById(id);
            user.setUsername(username);
            // 更新一条数据
            userMapper.updateById(user);
    
        }
    
        @Override
        public User selectUserByUsername(String username) {
            Wrapper<User> wrapper = new EntityWrapper<>();
            wrapper.eq("username", username);
            List<User> list = userMapper.selectList(wrapper);
            if(list.size()>0) {
                return list.get(0);
            }
            return null;
        }
    
    }

    11、创建UserRealm类

    package com.cppdy.realm;
    
    import java.util.ArrayList;
    import java.util.List;
    
    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.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 com.baomidou.mybatisplus.mapper.EntityWrapper;
    import com.baomidou.mybatisplus.mapper.Wrapper;
    import com.cppdy.entity.Permission;
    import com.cppdy.entity.Role;
    import com.cppdy.entity.User;
    import com.cppdy.mapper.PermissionMapper;
    import com.cppdy.mapper.RoleMapper;
    import com.cppdy.service.UserService;
    
    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        private UserService userService;
        @Autowired
        private RoleMapper roleMapper;
        @Autowired
        private PermissionMapper permissionMapper;
    
        // 控制角色权限
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            String username = (String) principals.getPrimaryPrincipal();
            // 将当前用户的角色和权限查询进来
            User user = userService.selectUserByUsername(username);
            Role role = roleMapper.selectById(user.getRoleid());
    
            info.addRole(role.getRolename());
    
            Wrapper<Permission> wrapper = new EntityWrapper<>();
            wrapper.eq("roleid", role.getId());
            List<Permission> selectList = permissionMapper.selectList(wrapper);
            ArrayList<String> perList = new ArrayList<String>();
            selectList.forEach(per -> {
                perList.add(per.getPername());
            });
    
            info.addStringPermissions(perList);
            return info;
        }
    
        // 控制登陆
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            AuthenticationInfo info = null;
            String username = (String) token.getPrincipal();
            User user = userService.selectUserByUsername(username);
            if (user != null) {
                info = new SimpleAuthenticationInfo(username, user.getPassword(), "cppdy");
            }
            return info;
        }
    
    }

    12、创建ShiroConfiguration配置类

    package com.cppdy.config;
    
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.Filter;
    
    import org.apache.shiro.cache.ehcache.EhCacheManager;
    import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
    import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
    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.web.servlet.SimpleCookie;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.cppdy.realm.UserRealm;
    
    @Configuration
    public class ShiroConfiguration {
        
        @Bean
        public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
            //必须设置SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //拦截器
            Map<String,String> filterChainDefinitionMap=new LinkedHashMap<String,String>();
            //配置静态资源允许访问
            filterChainDefinitionMap.put("/user/login", "anon");
            filterChainDefinitionMap.put("/user/loginAction", "anon");
            //authc:所有url都必须认证通过才可以访问;anon:所有url都可以匿名访问
            filterChainDefinitionMap.put("/**", "authc");
            //如果不设置默认会自动寻找web工程跟目标下的/login.jsp页面
            shiroFilterFactoryBean.setLoginUrl("/user/login");
            //未授权界面
    //        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
            Map<String,Filter> filters=new HashMap<String,Filter>();
            shiroFilterFactoryBean.setFilters(filters);
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            
            return shiroFilterFactoryBean;
        }
        
        @Bean
        public EhCacheManager getEhCacheManager() {
            EhCacheManager em=new EhCacheManager();
            em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
            return em;
        }
        
        //开启Controller中的shiro注解
        @Bean
        public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator daap=new DefaultAdvisorAutoProxyCreator();
            daap.setProxyTargetClass(true);
            return daap;
        }
        
        @Bean
        public DefaultWebSessionManager getDefaultWebSessionManager() {
            DefaultWebSessionManager defaultWebSessionManager=new DefaultWebSessionManager();
            defaultWebSessionManager.setSessionDAO(getMemorySessionDAO());
            defaultWebSessionManager.setGlobalSessionTimeout(4200000);
            defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
            defaultWebSessionManager.setSessionIdCookieEnabled(true);
            defaultWebSessionManager.setSessionIdCookie(getSimpleCookie());
            return defaultWebSessionManager;
        }
        
        @Bean
        public MemorySessionDAO getMemorySessionDAO() {
            MemorySessionDAO memorySessionDAO=new MemorySessionDAO();
            memorySessionDAO.setSessionIdGenerator(javaUuidSessionIdGenerator());
            return memorySessionDAO;
        }
        
        @Bean
        public JavaUuidSessionIdGenerator javaUuidSessionIdGenerator() {
            
            return new JavaUuidSessionIdGenerator();
        }
        
        /**
         * session自定义cookie名
         * @return
         */
        @Bean
        public SimpleCookie getSimpleCookie() {
            SimpleCookie simpleCookie=new SimpleCookie();
            simpleCookie.setName("security.session");
            simpleCookie.setPath("/");
            return simpleCookie;
        }
        
        @Bean
        public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
            
            return new LifecycleBeanPostProcessor();
        }
        
        @Bean(name="securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
            DefaultWebSecurityManager dwsm=new DefaultWebSecurityManager();
            dwsm.setRealm(userRealm);
            //用户授权/认证信息Cache,采用EhCache缓存
            dwsm.setCacheManager(getEhCacheManager());
            dwsm.setSessionManager(getDefaultWebSessionManager());
            return dwsm;
        }
        
        @Bean
        public UserRealm userRealm(EhCacheManager cacheManager) {
            UserRealm userRealm=new UserRealm();
            userRealm.setCacheManager(cacheManager);
            return userRealm;
        }
        
        /**
         * 开启shiro注解支持
         * @param userRealm
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(UserRealm userRealm) {
            AuthorizationAttributeSourceAdvisor aasa=new AuthorizationAttributeSourceAdvisor();
            aasa.setSecurityManager(getDefaultWebSecurityManager(userRealm));
            return aasa;
        }
    }

    13、创建UserController类

    package com.cppdy.controller;
    
    import org.apache.ibatis.session.RowBounds;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.apache.shiro.crypto.hash.Md5Hash;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.baomidou.mybatisplus.mapper.EntityWrapper;
    import com.baomidou.mybatisplus.mapper.Wrapper;
    import com.cppdy.entity.User;
    import com.cppdy.mapper.UserMapper;
    
    @RestController
    @RequestMapping("user")
    public class UserController {
    
        @Autowired
        private UserMapper userMapper;
    
        @RequestMapping("getUserById")
        public Object getUserById(int id) {
    
            return userMapper.selectById(id);
        }
    
        @RequiresPermissions("sys:delete")
        @RequestMapping("deleteUserById")
        public Object deleteUserById(int id) {
    
            return userMapper.deleteById(id);
        }
    
        @RequiresRoles("admin")
        @RequestMapping("getUser")
        public Object getUser() {
            // 适配器
            Wrapper<User> wrapper = new EntityWrapper<>();
            wrapper.like("username", "测试");
            // 倒序
            wrapper.orderBy("id", false);
            return userMapper.selectList(wrapper);
        }
    
        @RequestMapping("selectPage")
        public Object selectPage(int pageNum, int pageSize) {
            // 适配器
            Wrapper<User> wrapper = new EntityWrapper<>();
    
            RowBounds rowBounds = new RowBounds((pageNum - 1) * pageSize, pageSize);
    
            return userMapper.selectPage(rowBounds, wrapper);
        }
    
        @RequestMapping("login")
        public String login() {
    
            return "loginPage";
        }
    
        @RequestMapping("loginAction")
        public String loginAction(String username,String password) {
            Subject subject = SecurityUtils.getSubject();
            String md5 = new Md5Hash(password, "cppdy").toString();
            AuthenticationToken token = new UsernamePasswordToken(username, md5);
            try {
                // 如果执行subject.login抛出异常,则证明登陆成功
                subject.login(token);
                return "login success";
            } catch (AuthenticationException e) {
                // 有异常则证明登陆错误
                e.printStackTrace();
                return "login failed";
            }
        }
    
    }

    14、创建表(user、role、permission),并添加测试数据(password为:123456;md5加密后的password为:9faea48dae4030f38bcd1ae6a4f7fc01)

     15、访问loginAction方法进行登录,再分别调用getUser和deleteUserById方法测试角色权限控制

  • 相关阅读:
    Mongodb 集群加keyFile认证
    MongoDB 3.0 常见集群的搭建(主从复制,副本集,分片....)
    JVM的垃圾回收机制详解和调优
    深入Java核心 Java内存分配原理精讲
    PLSQL Developer win7 64位 安装方法
    nginx作为负载均衡服务器——测试
    Nginx负载均衡配置
    nginx集群报错“upstream”directive is not allow here 错误
    Nginx反向代理和负载均衡——个人配置
    Quartz集群配置
  • 原文地址:https://www.cnblogs.com/jiefu/p/10051845.html
Copyright © 2020-2023  润新知