Spring Boot 集成Shiro
- maven引入依赖
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.0</version>
</dependency>
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
其余的依赖省略,注意,如果要使用shiro注解控制权限,一定要引入aop
- 写shiro配置类,ShiroConfig
@Configuration
public class ShiroConfig {
//注入自定义的realm,告诉shiro如何获取用户信息来做登录或权限控制
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
@Bean
public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
/**
* setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
* 在@Controller注解的类的方法中加入@RequiresRole注解,会导致该方法无法映射请求,导致返回404。
* 加入这项配置能解决这个bug
*/
creator.setUsePrefix(true);
return creator;
}
@Bean
public Authenticator authenticator() {
Authenticator authenticator = new ModularRealmAuthenticator();
return authenticator;
}
@Bean
public Authorizer authorizer() {
Authorizer authorizer = new ModularRealmAuthorizer();
return authorizer;
}
@Bean
public SessionManager sessionManager() {
SessionManager sessionManager = new DefaultWebSessionManager();
return sessionManager;
}
/**
* 注入 securityManager
* @return
*/
@Bean
public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(userRealm);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
shiroFilterFactoryBean.setLoginUrl("/noLogin");
// 设置无权限时跳转的 url(无用,会被全局异常拦截)
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
// 设置拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//开放登陆接口
filterChainDefinitionMap.put("/user/**", "anon");
// filterChainDefinitionMap.put("/test/**", "anon");
//其余接口一律拦截
//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}
}
Authenticator、Authorizer、SessionManager必须注入,否则会报错,这里使用默认配置,也可以自定义
- shiro权限验证以及登录认证类,自定义realm,UserRealm
public class UserRealm extends AuthorizingRealm {
@Resource
private UserInfoMapper userInfoMapper;
/**
* 权限验证
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//得到当前登录对象
UserInfo userInfo = (UserInfo) principalCollection.getPrimaryPrincipal();
//权限集合
Set<String> permissionSet = new HashSet<>();
Set<String> roleSet = new HashSet<>();
permissionSet.add("user:add");
roleSet.add("admin");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissionSet);
simpleAuthorizationInfo.setRoles(roleSet);
return simpleAuthorizationInfo;
}
/**
* 密码加密方式
* @param credentialsMatcher
*/
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(1024);
super.setCredentialsMatcher(hashedCredentialsMatcher);
}
/**
* 登录认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//Principal 当事人
//Credentials 认证信息
//获取登录用户名
String username = (String) authenticationToken.getPrincipal();
//realm名字
String realmName = super.getName();
//这里做登陆信息验证。。。
UserInfo userInfo = userInfoMapper.findByUsername(username);
if (userInfo==null) {
//用户名不存在
throw new UnknownAccountException();
}
//盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo simpleAuthenticationInfo =
new SimpleAuthenticationInfo(userInfo, userInfo.getPassword(), credentialsSalt, realmName);
return simpleAuthenticationInfo;
}
}