博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot2.0集成Shiro
阅读量:3959 次
发布时间:2019-05-24

本文共 8590 字,大约阅读时间需要 28 分钟。

慕课Shiro安全框架入门()在学习的时候,前三章还是不错的,第四章Spring集成Shiro内容老些过时了,推荐给大家一个博主的博客(),写的挺不错

 

虽然博主已经很详细的讲解了整合的内容,但我还是觉得有些地方不是很清楚对于新手,下面写一些自己的观点,如有错误,欢迎指正

 

我们先看一下自定义realm的代码

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.crypto.hash.Md5Hash;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;public class CustomRealm extends AuthorizingRealm {    Map
userMap = new HashMap
(16); { //81dc9bdb52d04dc20036dbd8313ed055 userMap.put("Mark","f2d9ffba24994ac1cbeff23d94ddb62a"); super.setName("CustomRealm"); //Thread.currentThread().setName();为当前线程设置名称 } protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); //模拟从数据库或缓存中获取角色数据 Set
roles = getRolesByUsername(username); Set
permissions = getPermissionsByUsername(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; } private Set
getPermissionsByUsername(String username) { Set
set = new HashSet
(); set.add("user:delete"); set.add("user:update"); return set; } private Set
getRolesByUsername(String username) { Set
set = new HashSet
(); set.add("admin"); set.add("user"); return set; } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //1、AuthenticationToken 主体传过来的认证信息中,获取用户名 String username = (String)token.getPrincipal(); //2、通过用户名到数据库中获取凭证 String password = getPasswordByUsername(username); if(password==null){ return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("Mark",password,"CustomRealm"); info.setCredentialsSalt(ByteSource.Util.bytes("Mark")); return info; } //模拟数据库查询凭证 private String getPasswordByUsername(String username) { return userMap.get(username); } public static void main(String[] args) { Md5Hash md5Hash = new Md5Hash("1234","Mark"); System.out.println(md5Hash.toString()); }}

以及测试类

import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.realm.text.IniRealm;import org.apache.shiro.subject.Subject;import org.junit.Test;import realm.CustomRealm;public class CustomRealmTest {    CustomRealm customRealm = new CustomRealm();    @Test    public void TestIniRealm(){        //1.构建 securitymanager环境        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();        defaultSecurityManager.setRealm(customRealm);        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();        matcher.setHashAlgorithmName("MD5");        matcher.setHashIterations(1);        customRealm.setCredentialsMatcher(matcher);        //2.主体提交认证请求        SecurityUtils.setSecurityManager(defaultSecurityManager);        Subject subject = SecurityUtils.getSubject();        UsernamePasswordToken token = new UsernamePasswordToken("Mark","1234");        subject.login(token);        System.out.println("isAuthenticated: "+subject.isAuthenticated());        subject.checkRole("admin");        subject.checkPermission("user:delete");    }}

 

接下来我们提出问题

一、在ShiroConfig,它是Shiro的配置文件,作为配置文件,它在授权和认证中扮演了什么角色呢?

我们看一下最基本的配置:ShiroConfig代码

我们发现Spring在整合Shiro时,有一个SecurityManager的bean在配置文件中

实际上,在上面的测试类中就已经把答案写出来了

在HomeIndexController被访问时,在从SecurityUtils里边创建一个 subject之前,spring会自动在上下文寻找securityManager的bean并注入到SecurityUtils中,因此配置文件只是在为原来将原来写在测试类中的各个组件拆分,将它们组装成spring的bean,并让它们在合适的上下文处注入

package com.cj.shirodemo.config;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.mgt.SecurityManager;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.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import java.util.LinkedHashMap;import java.util.Map;/** * 描述: * * @author caojing * @create 2019-01-27-13:38 */@Configurationpublic class ShiroConfig {    @Bean(name = "shiroFilter")    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();        shiroFilterFactoryBean.setSecurityManager(securityManager);        shiroFilterFactoryBean.setLoginUrl("/login");        shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");        Map
filterChainDefinitionMap = new LinkedHashMap<>(); //
filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/front/**", "anon"); filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/admin/**", "authc"); filterChainDefinitionMap.put("/user/**", "authc"); //主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setRealm(customRealm()); return defaultSecurityManager; } @Bean public CustomRealm customRealm() { CustomRealm customRealm = new CustomRealm(); return customRealm; }}

二、在CustomRealm,它是Shiro授权和认证的核心,那么它都起到了哪些作用?

如上,先上代码

最简单的CustomRealm,它继承自AuthorizingRealm复写了父类的两个方法,即授权和认证,实际上正是通过这两个方法的返回结果来达到安全认证目的

package com.cj.shirodemo.config;import org.apache.shiro.SecurityUtils;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.apache.shiro.util.ByteSource;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.stereotype.Component;import java.util.HashSet;import java.util.Set;/** * 描述: * * @author caojing * @create 2019-01-27-13:57 */public class CustomRealm extends AuthorizingRealm {    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        String username = (String) SecurityUtils.getSubject().getPrincipal();        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        Set
stringSet = new HashSet<>(); stringSet.add("user:show"); stringSet.add("user:admin"); info.setStringPermissions(stringSet); return info; } /** * 这里可以注入userService,为了方便演示,我就写死了帐号了密码 * private UserService userService; *

* 获取即将需要认证的信息 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("-------身份认证方法--------"); String userName = (String) authenticationToken.getPrincipal(); String userPwd = new String((char[]) authenticationToken.getCredentials()); //根据用户名从数据库获取密码 String password = "123"; if (userName == null) { throw new AccountException("用户名不正确"); } else if (!userPwd.equals(password )) { throw new AccountException("密码不正确"); } return new SimpleAuthenticationInfo(userName, password,getName()); }}

其余部分,博主已经总结很详细了,不再复述

转载地址:http://eoazi.baihongyu.com/

你可能感兴趣的文章
图文混排效果
查看>>
urllib2.urlopen超时问题
查看>>
Choosing a Machine Learning Classifier
查看>>
魏兴国:深入浅出DDoS攻击防御
查看>>
使连续的参考文献能够中间用破折号连起来
查看>>
Discover Feature Engineering, How to Engineer Features and How to Get Good at It
查看>>
36辆车,6条跑道,无计时器,最少几次比赛可以选出前三
查看>>
matlab2012b与matlab7.1执行set(gca,'Yscale','log')之后画到的直方图结果居然不同
查看>>
python读大文件
查看>>
python 3里没有cmp这个函数了
查看>>
回文题
查看>>
二叉树的最短根到叶路径中点的个数
查看>>
给定二叉树求最小深度
查看>>
平衡树
查看>>
栈的应用题(1)
查看>>
判断链表是否有环
查看>>
从有序链表中去掉重复的
查看>>
后台程序结果重定向到文件,结果看不到文件?缓冲区的问题
查看>>
[LeetCode]Reverse Integer
查看>>
DNS采用的传输层协议可能是TCP或UDP
查看>>