最近来新项目, 后台管理, 说道管理, 肯定是需要权限; 又把之前看的shiro拿出来用, 因为之前用的springMVC, 懂的也是半吊子, 这次用springboot也费老劲了, 但是还是让我把它的基本用法搞懂了, 下面分享下;
1.上jar包
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
2.shiro配置类
package cn.cooplan.data_statistical.config;
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.boot.autoconfigure.condition.ConditionalOnMissingBean;
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 MaoLG
* @Date 2018/11/17 11:24
*/
@Configuration
public class ShiroConfig {
/**
* LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,
* 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。
* 主要是AuthorizingRealm类的子类,以及EhCacheManager类。
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,
* 负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
* 这个类是我自己定义的, 因为要根据自己实际需求来进行权限校验
*/
@Bean(name = "shiroRealm")
@DependsOn("lifecycleBeanPostProcessor")
public ShiroRealm shiroRealm() {
ShiroRealm realm = new ShiroRealm();
return realm;
}
/**
* SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
*
* @return
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}
/**
* ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。
* 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
* 该类类似springmvc配置的访问权限设置
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
//url权限配置, url为controller设置的可访问的路径 ps:url可以使用*(通配符设置)
Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
//可以匿名访问的权限 anon:不登录也可访问
filterChainDefinitionManager.put("/user/login", "anon");
//必须登录的权限 authc:必须登录才能访问的权限
filterChainDefinitionManager.put("/user/test", "authc");
//退出登录 logout:退出登录, shiro帮我们实现, 该路径方法可不编写任何逻辑,可清楚shiro记录的认证
// 每次去认证的时候, 如果不调用该接口, 不会访问数据库去认证 会直接从shiro的缓存中拿取认证信息, 在适当情况调用该接口
filterChainDefinitionManager.put("/user/logout", "logout");
//权限访问, 不能动态获取, 代码写死, 没找到动态获取方法
filterChainDefinitionManager.put("/user/test", "perms[测试]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
return shiroFilterFactoryBean;
}
/**
* DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
*/
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
/**
* AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,
* 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor();
aASA.setSecurityManager(securityManager());
return aASA;
}
}
3.自定义realm
package cn.cooplan.data_statistical.config;
import cn.cooplan.data_statistical.dao.PermissionDao;
import cn.cooplan.data_statistical.dao.UserDao;
import cn.cooplan.data_statistical.pojo.Permission;
import cn.cooplan.data_statistical.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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 java.util.List;
/**
* 自定义realm
*
* @Author MaoLG
* @Date 2018/11/17 13:03
*/
public class ShiroRealm extends AuthorizingRealm {
//读取用户权限,我这里没有角色表, 具体根据自己实际需求编写
@Autowired
private PermissionDao permissionDao;
/**
* 授权
* 实现授权具体业务
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获得登录时提供的重要凭证, 这里获得的是登录账号
String username = (String) principalCollection.getPrimaryPrincipal();
//查询到该账号下所有的权限
List<Permission> permissions = permissionDao.selectUserOwnPermission(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//把用处所有权限加在SimpleAuthorizationInfo 对象中, shiro自己来读取对比权限
for (Permission permission: permissions){
info.addStringPermission(permission.getName());
}
//如果有角色的需要, 调用info.addRole("角色"); 同权限一个道理
return info;
}
/**
* 认证
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
SimpleAuthenticationInfo info = null;
try {
//强转UsernamePasswordToken 类型
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//获得登录账号
String username = token.getUsername();
char[] pwd = token.getPassword();
//获得登密码
String password = String.valueOf(pwd);
//shiro默认配置回去找t_user表 来查询 , 也可根据自己实际业务编写
info = new SimpleAuthenticationInfo(username, password, getName());
} catch (Exception e) {
e.printStackTrace();
}
return info;
}
}
这里没有使用rememberMe(记住我--实现自动登录), 有需要的大家自行先百度, 后期如果使用到会更新上去