shiro学习和使用实例(2)——登陆认证和授权
来源:互联网 发布:美术教程视频软件 编辑:程序博客网 时间:2024/06/01 09:15
技术背景, 控制转发用的是springMVC,持久化层使用Mybatis,缓存用redis,前台框架easyUI,自动化构建项目使用maven
一、导包
maven引入使用shiro所需的包
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-core</artifactId>
- <version>1.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-web</artifactId>
- <version>1.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring</artifactId>
- <version>1.2.1</version>
- </dependency>
二、登陆
- @RequestMapping(value = "/login")
- OperationPrompt login(String userID, String password,boolean rememberMe)
- throws NoSuchAlgorithmException {
- OperationPrompt op = null;
- String encodePassword = setEncrypting(password);//加密密码
- try{
- UsernamePasswordToken token = new UsernamePasswordToken(userID,encodePassword, false);
- token.setRememberMe(rememberMe);//设置记住我 自动登录
- SecurityUtils.getSubject().login(token);
- op = new OperationPrompt("用户登录成功", true);
- }catch(AuthenticationException ae){
- logger.error(ae);
- op = new OperationPrompt(ae.getMessage(), false);
- return op;
- }catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- //查出用户所有角色的权限(包括会员等级的高级设置)
- List<Permission> permissions = new ArrayList<Permission>();
- com.isoftstone.securityframework.api.domain.Permission p = new com.isoftstone.securityframework.api.domain.Permission();
- p.setId(1);
- permissions.add(p);
- //避免空指针
- jedisPoolManager.set(SerializeUtils.serialize("permission:"+userID), SerializeUtils.serialize(permissions));
- //登陆成功后强制加载shiro权限缓存 避免懒加载 先清除
- restAuthRealm.forceShiroToReloadUserAuthorityCache();
- return op;
- }
- /**
- * user login
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException {
- UsernamePasswordToken authToken = (UsernamePasswordToken) token;
- String accountId = authToken.getUsername();
- String password = String.valueOf(authToken.getPassword());
- // 登陆方法需要添加 平台参数 系统参数过滤
- AccountQuery query = new AccountQuery();
- query.setAccountId(accountId);
- query.setEmail(accountId);
- query.setMoblie(accountId);
- query.setPlatformId(platformLabel);
- query.setSubSystemId(systemLabel);
- //获取账户信息
- com.isoftstone.securityframework.api.domain.Account domainAccount =
- (com.isoftstone.securityframework.api.domain.Account)accountManagerImpl.getAccount(accountId,platformLabel,systemLabel);
- //判断用户是否存在
- if (null == domainAccount){
- throw new UnknownAccountException(String.format("账号[%s]不存在!", accountId));
- }
- //检查用户密码是否匹配
- if (!domainAccount.getPassword().equals(password)){
- throw new IncorrectCredentialsException (String.format("[%s]密码错误!", accountId));
- }
- //检查账号是否激活
- if(STATUS_NOTACTIVATED == domainAccount.getStatus()){
- throw new AuthenticationException (String.format("用户名[%s]未激活!", accountId));
- }
- //检查账号是否已冻结
- if(STATUS_FREEZEEXCED == domainAccount.getStatus()){
- throw new AuthenticationException (String.format("账号[%s]已冻结", accountId));
- }
- //检查账号身份是否冻结
- AccountCommon accountCommon = domainAccount.getAccCommon();
- if(accountCommon!=null){
- if(accountCommon.getIsBuyer()!=4 &&accountCommon.getIsSaler()!=4){
- throw new AuthenticationException (String.format("账号[%s]已经被冻结", accountId));
- }
- }
- //设置登录时间
- domainAccount.setLastLoginTime(DateUtils.getToday(DateUtils.TIMEF_FORMAT));
- accountManagerImpl.modify(domainAccount);
- Account authAccount = new Account();
- this.copyPropertiesToAuthAccount(domainAccount,authAccount);
- //设置已认证的用户信息到用户对象中
- SimpleAuthenticationInfo simpleAuthInfo = new SimpleAuthenticationInfo(authAccount,authAccount.getPassword(),getName());
- return simpleAuthInfo;
- }
我们自定义的这个realm(restAuthRealm)继承AuthorizingRealm,认证逻辑写在doGetAuthenticationInfo方法中,根据前台传入的用户名和其他条件从数据库中查找出账号与前台传入的密码比对,判断是否为系统合法用法。当然还可以有其他的判断,比如这里的账号是否激活,是否冻结,是否存在。认证完成之后将已认证的用户信息返回。根据我的理解,返回的该用户信息应该存储在了redis的缓存中,以便系统其他地方用到当前登陆人的信息。
接着,我们回到上面controller层的login方法,用户名、密码认证通过后,我们需要把原来缓存中的权限信息清除,也就是clear掉原来的授权信息SimpleAuthorizationInfo。
//登陆成功后强制加载shiro权限缓存 避免懒加载 先清除
restAuthRealm.forceShiroToReloadUserAuthorityCache();
完成这个操作,需要在我们自己定义的realm(restAuthRealm)中实现clearCachedAuthorizationInfo()方法,代码如下:
- /**
- * 更新用户授权信息缓存.
- */
- public void clearCachedAuthorizationInfo(Object principal) {
- SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
- clearCachedAuthorizationInfo(principals);
- }
- //登陆成功后强制加载shiro权限缓存 避免懒加载 先清除
- public void forceShiroToReloadUserAuthorityCache(){
- this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipal());
- this.isPermitted(SecurityUtils.getSubject().getPrincipals(),"强制加载缓存,避免懒加载"+ System.currentTimeMillis());
- }
- /**
- * user permission query(Get authorization info from Cache first or get info from remote service )
- */
- @SuppressWarnings("unchecked")
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(
- PrincipalCollection principals) {
- Account account1 = (Account)getAvailablePrincipal(principals);
- com.isoftstone.securityframework.api.domain.Account account = (com.isoftstone.securityframework.api.domain.Account) accountManagerImpl.get(account1.getId());
- List<com.isoftstone.securityframework.api.Permission> perms = new ArrayList<Permission>();
- //从数据库中查询权限
- perms = rolePermissionRealm.getSubjectPermission(account);
- Set<String> permSet = new HashSet<String>();
- if(null != perms){
- for (Permission perm : perms) {
- String permissionName = perm.getPermissionName();
- //将前缀去掉
- int beginIndex = platformLabel.length() +systemLabel.length()+2;
- permissionName = permissionName.substring(beginIndex);
- permSet.add(permissionName);
- }
- }
- SimpleAuthorizationInfo simpleAuthInfo = new SimpleAuthorizationInfo();
- simpleAuthInfo.setStringPermissions(permSet);
- return simpleAuthInfo;
- }
至此,登陆成功,shiro完成了两件事,其一,前台传过来的用户名和密码认证通过,其二,清除了原来缓存(redis)中的授权信息(权限),加上了当前用户最新的权限信息,方便后面的鉴权。
鉴权方面,我会另外再写一篇博客来和大家讨论。
存在不足:1、登陆时记住我这个功能没有详细描述
2、isPermitted鉴权判断,权限标识未做说明- shiro学习和使用实例(2)——登陆认证和授权
- shiro学习和使用实例(2)——登陆认证和授权
- Shiro案例---认证和授权
- 【shiro】授权和认证流程
- shiro学习和使用实例(3)——鉴权
- shiro学习和使用实例(3)——鉴权
- shiro学习和使用实例(1)
- shiro学习和使用实例(1)
- spring整合shiro认证和授权
- Shiro认证流程和授权流程
- SpringBoot学习(四)--集成shiro实现基础登陆认证和权限管理
- 通过shiro认证身份和模拟授权认证
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
- 使用shiro实现登陆认证
- Spring Shiro配置实现用户认证和授权
- shiro权限框架中的认证和授权过程
- Spring Shiro配置实现用户认证和授权
- Shiro的permission管理,用户的认证和授权
- Win7 下基于 Oracle VM VirtualBox 安装 fedora8
- SVN安装、配置、使用笔记
- Windows下面替换命令实现,最新修复一个BUG
- Linux 的变量命名规则
- SizeClass和AutoLayout教程1
- shiro学习和使用实例(2)——登陆认证和授权
- Linux TCP队列相关参数的总结
- 错误711:操作无法完成,因为它无法及时启动远程访问连接管理服务 宽带连接提示错误711的解决办法
- Android特效 五种Toast详解
- Java数据类型字节数
- 关于Android中添加id
- Ultra-QuickSort
- CocoaPods安装和使用详细说明
- 剑指offer 栈的压入、弹出序列