SpringBoot框架现阶段使用的比较频繁,但是Spring家族中的安全管理框架(Spring Security)的功能虽然强大,但是他是给予Spring的,不能单独使用,而Shiro则相对简单,容易上手,所以这里简单记录一下SpringBoot框架集成Shiro。
首先要有一个 SpringBoot的架构,我的springboot的目录为
整合主要在这个框架中加入两个实现类,功能分别为
- 登录权限验证以及角色验证
- 配置要拦截的接口,以及密码的加密等等
需要导入的jar包为:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
下面为第一个实现类
public class ShiroRealm extends AuthorizingRealm {
/**
* 1.doGetAuthenticationInfo,获取认证消息,如果数据库中没有数,返回null,如果得到了正确的用户名和密码,
* 返回指定类型的对象
*
* 2.AuthenticationInfo 可以使用SimpleAuthenticationInfo实现类,封装正确的用户名和密码。
*
* 3.token参数 就是我们需要认证的token
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
//认证登录
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 1.将token装换成UsernamePasswordToken
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
logger.info("验证当前Subject时获取到token为:" + upToken.toString());
// 2.获取用户名即可
String username = upToken.getUsername();
// 3.查询数据库,是否查询到用户名和密码的用户
UserInfoEntity userInfo = userInfoService.selectByPhone(username);
if(userInfo != null) {
// 4.如果查询到了,封装查询结果,返回给我们的调用
Object principal = userInfo.getPhoneNumber();
Object credentials = userInfo.getPassword();
ByteSource salt = ByteSource.Util.bytes(username);
String realmName = this.getName();
info = new SimpleAuthenticationInfo(principal, credentials, salt,realmName);
}else {
// 5.如果没有查询到,抛出一个异常
throw new AuthenticationException();
}
return info;
}
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
logger.info("##################执行Shiro权限认证##################");
String username = (String) principalCollection.getPrimaryPrincipal();
EnterpriseInfoEntity user = enterpriseInfoEntityMapper.selectByPhone(username);
if (user != null) {
//权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//用户的角色集合
Set<String> list = new HashSet<>();
list.add(user.getAuditStatus());
info.addRoles(list);
//用户的权限集合
info.addStringPermissions(list);
return info;
}
// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址
return null;
}
}
代码里的注释都很全,这里就不做过多的介绍了,继续来看第二个类
package com.aim.chenapp.config;
import com.aim.chenapp.beans.ShiroRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不会被拦截的链接 顺序判断
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
//静态资源
//filterChainDefinitionMap.put("/myTest/**", "anon");
//需要企业用户权限的接口
filterChainDefinitionMap.put("/newsInfo/selectNewsBySecond", "authc,roles[1]");//政策解读
filterChainDefinitionMap.put("/newsInfo/selectByCustomized", "authc,roles[1]");//法律定制
// filterChainDefinitionMap.put("/user/login", "anon");
// filterChainDefinitionMap.put("/user/unPower", "anon");
// filterChainDefinitionMap.put("/user/doRegister", "anon");
filterChainDefinitionMap.put("/**", "anon");
//配置这个接口只能由admin这个角色访问
filterChainDefinitionMap.put("/user/selectAll", "authc,roles[admin]");
// filterChainDefinitionMap.put("/user/doLogout", "logout");
//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/user/unPower");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean(name = "myShiroRealm")
public ShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){
ShiroRealm myShiroRealm = new ShiroRealm();
// HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
// matcher.setHashIterations(1024);
myShiroRealm.setCredentialsMatcher(matcher);
return myShiroRealm;
}
@Bean
public SecurityManager securityManager(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm(matcher));
return securityManager;
}
/**
* 密码匹配凭证管理器
*
* @return
*/
@Bean(name = "hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于
// md5(md5(""));
return hashedCredentialsMatcher;
}
}
这个就是SpringBoot框架整合Shiro的全部过程,如果有什么问题欢迎留言探讨。
青春短暂,我_在路上