今天加班,事情做的差不多,先前对Springboot 整合 shiro 有稍微研究一下下,但项目搭建好后,都是一直的复用复用,时间一长,都忘记整合流程了,网上Springboot 整合 shiro 教程也有很多,我呢,也没有什么太大的特色,就想搞个由浅入深,从初级整合到进阶版,增加redis作为缓存,一步一步来,方便学习也方便自己记忆。
首先,我们要整合是初级版,只有 Springboot 整合 shiro,步骤如下:
-
初级版:
第一步:导包:
如果一切都从 Hello World 开始,整合也都是从 pom.xml 文件中引入 shiro的jar包
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
第二步:编写 shiro 自定义认证类 Realm
在自定义的Realm 中,根据实际业务,完善相应的密码校验和鉴权授权代码
import com.workbench.sys.SysAccount;
import org.apache.commons.beanutils.ConvertUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* 自定义shiro验证
* @Auther: He
* @Create_Date: 2020/8/30 10:55
*/
public class MyShiroRealm extends AuthorizingRealm {
/**
* 对登录账号进行鉴权授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println(">>>> 鉴权授权 <<<<");
//获取登录用户名
String account = (String) principalCollection.getPrimaryPrincipal();
//根据用户名去数据库查询用户信息
// SysAccount sysAccount = iSysAccountService.selectSysAccountInfoByAccount(account);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// for (Role role : user.getRoles()) {
// //添加角色
// simpleAuthorizationInfo.addRole(role.getRoleName());
// //添加权限
// for (Permissions permissions : role.getPermissions()) {
// simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
// }
// }
return simpleAuthorizationInfo;
}
/**
* 校验登录账户是否正确
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println(">>>>> 登录认证 <<<<<");
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String account = authenticationToken.getPrincipal().toString();
//模拟数据库查询
SysAccount sysAccount = new SysAccount();
sysAccount.setAccount("abc");
sysAccount.setPassword("123");
if (sysAccount == null) {
//这里返回后会报出对应异常
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(account, sysAccount.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
}
/**
* RealmSecurityManager rsm = (RealmSecurityManager)SecurityUtils.getSecurityManager();
AuthRealm authRealm = (AuthRealm)rsm.getRealms().iterator().next();
authRealm.clearAuthz();
*/
public void clearAuthor(){
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
public void clearAuthen(){
this.clearCachedAuthenticationInfo(SecurityUtils.getSubject().getPrincipals());
}
}
第三步:编写配置类 ShiroConfig
Shiro 配置类中设置相应的拦截规则,并添加注册自定义的验证类
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.*;
/**
* Shiro 配置类
* @Auther: He
* @Create_Date: 2020/8/30 10:59
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 配置不会被拦截的链接 按顺序判断
//登录
filterChainDefinitionMap.put("/sys/login", "anon");
filterChainDefinitionMap.put("/staff/auth/mobileCode", "anon");
filterChainDefinitionMap.put("/staff/auth/forgetPassword", "anon");
filterChainDefinitionMap.put("/sys/attachment/upload", "anon");
filterChainDefinitionMap.put("/sys/attachment/selectImg", "anon");
//authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/**", "authc,perms");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授权界面;
// shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 凭证匹配器
* (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* )
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(1);//散列的次数,比如散列两次,相当于 md5(md5(""));
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
return hashedCredentialsMatcher;
}
@Bean
public MyShiroRealm myShiroRealm(){
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
}
设置拦截规则时,切记要把 登录请求设置成 anon ,即免登陆访问,
如:filterChainDefinitionMap.put("/sys/login", "anon");
第四步:编写controller类进行校验
/**
* 登录方法
* @param request
* @param sysAccount
* @return
*/
@RequestMapping(value = "/login")
public Result<SysAccount> login(HttpServletRequest request, @RequestBody SysAccount sysAccount) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(sysAccount.getAccount(), sysAccount.getPassword());
subject.login(usernamePasswordToken);
Session session = SecurityUtils.getSubject().getSession();
return getResult(Result.OK, session);
}
接下来就是使用 Postman 等工具进行测试了。
至此,初级版的 Springboot 整合 Shiro 就完成了。
进阶版的后面更新
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 我是一条华丽的分割线 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<