前言
在系统管理中,权限是非常重要的一个环节。目前权限框架中使用比较多的有Shiro、Spring Security。🎃
本篇简单写一下SpringBoot整合Shiro权限框架小栗子🌰。
个人博客地址:SpringBoot整合Shiro权限框架
介绍Shiro
Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro 要简单的多。++更多详细介绍参考:w3cschool-shiro++
🚀开始
创建项目就不多嗦了,直接上干货~~
相关依赖
<!-- web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 剔除spring logging依赖,防止与log4j2冲突 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- shiro 安全框架-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.6.0</version>
</dependency>
系统配置
shiro权限的主要配置部分分为:
- subject(可以认为是一个认证对象,与当前应用交互的任何东西都是subject)
- securityManager(安全管理器,所有安全相关的东西都是跟它交互的,它管理着所有的subject)
- realm(可以认为是一个安全信息数据源,主要通过校验subject是否符合安全策略。所以我们在使用shiro时,需要先配置自己的realm)。
配置Realm
话不多说上代码~ 这里先以登录认证作为粟子
@Slf4j
public class MyShiroRealm extends AuthorizingRealm {
@Resource
private SysUserService sysUserService;
/**
* 授权信息配置
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 主要以登录认证作为例子, 此处暂时不做认证, 之后例子做补充
return null;
}
/**
* 登录认证信息
* @param token token
* @return 认证信息
* @throws AuthenticationException e
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 返回认证信息, 一般为用户名
Object principal = token.getPrincipal();
if (ObjectUtil.isNull(principal)) {
return null;
}
// 获取数据库中用户信息
String loginName = principal.toString();
SysUser user = sysUserService.findSysUserByName(loginName);
if (null == user) {
log.debug("{} - 登录用户不存在!", loginName);
throw new UnknownAccountException("登录用户不存在!");
}
// 使用盐加密 构造方法
ByteSource credentialsSalt = ByteSource.Util.bytes(loginName);;
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getLoginPwd(), credentialsSalt, getName());
// 验证信息
//SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getLoginPwd(), getName());
log.debug("验证登录信息: {} ===>>>> {}", loginName, simpleAuthenticationInfo.getPrincipals());
return simpleAuthenticationInfo;
}
}
配置安全策略
增加完Realm域配置,我们需要让此配置生效,所以需要将它添加给Shiro的安全管理策略。
/**
* 自定义安全管理策略
*/
@Bean
public SecurityManager securityManager(MyShiroRealm myShiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置自定义的realm
securityManager.setRealm(myShiroRealm);
return securityManager;
}
/**
* 地址过滤器
*
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置安全管理
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 设置登录地址
shiroFilterFactoryBean.setLoginUrl("/login");
// 设置主页地址
shiroFilterFactoryBean.setSuccessUrl("/index");
// 设置未授权的url
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 开放登录接口
filterChainDefinitionMap.put("/doLogin", "anon");
// 生成验证码接口
filterChainDefinitionMap.put("/captcha/captchaImg", "anon");
// 开放静态资源文件
filterChainDefinitionMap.put("/assets/**", "anon");
// 其余url全部拦截,必须放在最后
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* shiro生命周期
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* shiro注解启用配置
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
sourceAdvisor.setSecurityManager(securityManager);
return sourceAdvisor;
}
登录
设置完自定义域,以及自定义策略我们shiro就可以进行下一步了,那就是接口认证操作,这里简单定义一个接口
/**
* 登录操作
*
* @param loginName 登录名
* @param loginPwd 登录密码
* @return url
*/
@ResponseBody
@PostMapping("/doLogin")
public Result<String> doLogin(String loginName, String loginPwd, String captcha, boolean rememberMe, HttpServletRequest request) {
// 验证码校验
String sessionCaptcha = (String) request.getSession().getAttribute(AppConstants.CAPTCHA_KEY);
if (!StringUtils.equalsIgnoreCase(captcha, sessionCaptcha)) {
return Result.error("验证码不匹配!");
}
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginName, loginPwd, rememberMe);
Subject subject = SecurityUtils.getSubject();
try {
// 认证操作
subject.login(usernamePasswordToken);
// 获取登录的用户
SysUser user = (SysUser) subject.getPrincipal();
// 将用户信息存入cookie中
Session session = subject.getSession();
session.setAttribute("user", user);
// 删除session验证码
request.getSession().removeAttribute(AppConstants.CAPTCHA_KEY);
} catch (UnknownAccountException e) {
log.debug("未知用户! {}", e.getMessage());
return Result.error("未知用户!");
} catch (IncorrectCredentialsException e) {
log.debug("{} - 用户登录密码校验异常! {}", loginName, e.getMessage());
return Result.error("密码校验异常!");
} catch (AuthenticationException e) {
log.debug("{} - 用户登录认证失败! {}", loginName, e.getMessage());
return Result.error("登录失败!");
} catch (Exception e) {
log.debug("{} - 用户登录异常! {}", loginName, e.getMessage());
return Result.error("登录异常!");
}
return Result.success("登录成功!");
}
测试
接口定义完,我们需要一个登录页面来完成登录认证操作,这里使用我之前写的登录页面来完成。

点击登录后观察接口执行情况:

当执行到subject.login()方法后,会进行认证操作,这时候就会执行到我们设置的自定义Realm。红框处是我们做完登录用户与数据库中比对过后,将用户信息存到了认证信息中并返回给接口。

最后页面成功跳转至新页面,我们就完成了登录认证操作啦。🕛
END
简单的完成了一个登录认证的操作,之后会慢慢更新shiro的其他功能😀

本文介绍了如何在SpringBoot项目中集成Shiro权限框架,包括添加依赖、配置Realm、安全策略和登录接口实现,以完成基本的用户认证和授权功能。
2万+

被折叠的 条评论
为什么被折叠?



