跟我學shiro——springboot集成shiro

準備工做

<dependency>
   <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-all</artifactId>
 <version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>

1:建立ShiroConfigBeanweb

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfigBean {
 
    @Bean
    public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
        System.out.println("初始化攔截器");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必須設置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 攔截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // 設置login URL
        shiroFilterFactoryBean.setLoginUrl("/login");
        //遊客,開發權限
        filterChainDefinitionMap.put("/guest/**", "anon");
        //用戶,須要角色權限 「user」
        filterChainDefinitionMap.put("/user/**", "roles[user]");
        //管理員,須要角色權限 「admin」
        filterChainDefinitionMap.put("/admin/**", "roles[admin]");
        //開放登錄接口
        filterChainDefinitionMap.put("/login", "anon");
        //其他接口一概攔截
        //主要這行代碼必須放在全部權限設置的最後,否則會致使全部 url 都被攔截
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
 
    /*
     * 憑證匹配器 (因爲咱們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
     * 因此咱們須要修改下doGetAuthenticationInfo中的代碼; )
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        System.out.println("密碼匹配器");
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:這裏使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1);// 散列的次數,好比散列兩次,至關於md5(md5(""));
        return hashedCredentialsMatcher;
    }
//
    @Bean
    public MyShiroRealm myShiroRealm() {
        System.out.println("進入relam");
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }
 
    @Bean
    public DefaultWebSecurityManager securityManager() {
        System.out.println("將relam注入到securityManager");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 注入自定義的realm;
        securityManager.setRealm(myShiroRealm());
        // 注入緩存管理器;
        securityManager.setCacheManager(ehCacheManager());

        return securityManager;
    }
 
    /*
     * 開啓shiro aop註解支持 使用代理方式;因此須要開啓代碼支持;
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            DefaultWebSecurityManager securityManager) {
        System.out.println("開啓註解模式");
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
 
    /**
     * DefaultAdvisorAutoProxyCreator,Spring的一個bean,由Advisor決定對哪些類的方法進行AOP代理。
     */
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }
 
    /*
     * shiro緩存管理器;
     * 須要注入對應的其它的實體類中-->安全管理器:securityManager可見securityManager是整個shiro的核心;
     */
    @Bean
    public EhCacheManager ehCacheManager() {
        System.out.println("shiro緩存");
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return cacheManager;
    }
}

2:編寫自定義的realm算法

import com.tuyue.entity.User;
import com.tuyue.mapper.PermissionMapper;
import com.tuyue.mapper.RoleMapper;
import com.tuyue.mapper.UserMapper;
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.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.apache.shiro.util.StringUtils;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

/**
 * realm實現類,用於實現具體的驗證和受權方法
 * @author Bean
 *
 */
public class MyShiroRealm extends AuthorizingRealm {
 @Autowired
 private UserMapper userMapper;
 @Autowired
 private RoleMapper roleMapper;
 @Autowired
 private PermissionMapper permissionMapper;
    /**
     * 方面用於加密 參數:AuthenticationToken是從表單穿過來封裝好的對象
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("開始驗證是否登陸" + token.getPrincipal());
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        // 得到從表單傳過來的用戶名
        String username = upToken.getUsername();
        if(username==null||username.length()==0){
            return null;
        }
        User user=new User();
        user.setUsername(username);
        User user1 = userMapper.selectOne(user);
        // 若是用戶不存在,拋此異常
        if (user1==null) {
            throw new UnknownAccountException("無此用戶名!");
        }
        // 認證的實體信息,能夠是username,也能夠是用戶的實體類對象,這裏用的用戶名
        Object principal = user1;
        // 顏值加密的顏,能夠用用戶名
        ByteSource credentialsSalt = ByteSource.Util.bytes("222");
        // 當前realm對象的名稱,調用分類的getName()
        String realmName = this.getName();
        // 建立SimpleAuthenticationInfo對象,而且把username和password等信息封裝到裏面用戶密碼的比對是Shiro幫咱們完成的
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, user1.getPassword(),credentialsSalt, realmName);
        return info;
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }
 
    // 用於受權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("受權方法執行");
        Set<String> roles = new HashSet<>();
        Set<String> permissions = new HashSet<>();
        User user= (User) principals.getPrimaryPrincipal();
        List<String> list = roleMapper.selectByUserId(user.getId());
        for (String s : list) {
            roles.add(s);
        }
        List<String> list1 = permissionMapper.selectByuserId(user.getId());
        for (String s : list1) {
            permissions.add(s);
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
        //添加權限
        info.setStringPermissions(permissions);
        return info;
    }
}

3:建立數據庫spring

USE `shiro`;

/*Table structure for table `permission` */

DROP TABLE IF EXISTS `permission`;

CREATE TABLE `permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `permission_name` varchar(20) DEFAULT NULL,
  `source` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

/*Data for the table `permission` */

insert  into `permission`(`id`,`permission_name`,`source`) values (1,'添加用戶','user:save'),(2,'刪除用戶','user:del'),(3,'修改用戶','user:up'),(4,'添加商品','goods:save'),(5,'修改商品','goods:up'),(6,'刪除商品','goods:del');

/*Table structure for table `permission_role` */

DROP TABLE IF EXISTS `permission_role`;

CREATE TABLE `permission_role` (
  `permission_id` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `permission_role` */

insert  into `permission_role`(`permission_id`,`role_id`) values (1,1),(2,1),(3,1),(4,2),(5,2),(6,2);

/*Table structure for table `role` */

DROP TABLE IF EXISTS `role`;

CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `role` */

insert  into `role`(`id`,`role_name`) values (1,'用戶管理員'),(2,'商品管理員');

/*Table structure for table `user` */

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `user` */

insert  into `user`(`id`,`username`,`password`) values (1,'123','c26a263602b986958afab92363c5984f'),(2,'456','456');

/*Table structure for table `user_role` */

DROP TABLE IF EXISTS `user_role`;

CREATE TABLE `user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `role_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `user_role` */

insert  into `user_role`(`id`,`user_id`,`role_id`) values (1,1,1),(2,2,2);

4:編寫controller進行測試
(1)先測試登陸數據庫

@RequestMapping("/login")
    public String loginUser(String username,String password) {
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(usernamePasswordToken);   //完成登陸
            boolean aaa = subject.hasRole("用戶管理員");
            System.out.println("2222"+aaa);
            return "登陸成功";
        } catch(Exception e) {
            e.printStackTrace();
            return "登錄失敗";
        }
        
    }

(2) 測試權限apache

@RequestMapping("test")
    @RequiresAuthentication
    @RequiresPermissions("user:del")
    public String test() {
        Subject subject = SecurityUtils.getSubject();
        return "當前對象:"+subject.getPrincipal().toString();
    }
相關文章
相關標籤/搜索