SpringBoot+Shiro+ehcache实现登录失败超次数锁定帐号

文章目录

            • 二、Controller层接收登录请求
            • 三、自定义的Realm
            • 四、密码验证器增加登录次数校验功能
            • 五、ShiroConfig的配置类
            • 六、EhCache 的配置
            • 七、全局异常的配置

####### 一、 Shiro的执行流程
在这里插入图片描述
1、核心介绍
1)Application Code用户编写代码
2)Subject就是shiro管理的用户
3)SecurityManager安全管理器,就是shiro权限控制核心对象,在编程时,只需要操作Subject方法,底层调用SecurityManager方法,无需直接编程操作SecurityManager
4)Realm应用程序和安全数据之间连接器,应用程序进行权限控制读取安全数据(数据表、文件、网络…)通过Realm对象完成
2、Shiro执行流程
应用程序(就是你自己的项目)—>Subject—>SecurityManager—>Realm—>安全数据
3、Shiro进行权限控制的四种主要方式
1)在程序中通过Subject编程方式进行权限控制
2)配置Filter实现URL级别粗粒度权限控制
3)配置代理,基于注解实现细粒度权限控制
4)在页面中使用shiro自定义标签实现,页面显示权限控制

Shiro执行登录的流程如下图.
在这里插入图片描述
大致的思路如下, 在Controller层接收前端输入的用户名和密码. 调用Shiro的SecurityUtils.getSubject()方法获取Subject对象.
之后用Subject对象调用login方法,其Shiro底层会进行密码的验证, 传入UsernamePasswordToken对象,此对象封装了前端传入的用户名和密码.
在这里插入图片描述
接着Shiro的SecurityManager会去调用自定义的Realm的AuthenticationInfo方法进行登录的验证, 此方法会返回一个SimpleAuthenticationInfo对象,此对象封装了ShiroUser ,数据库中存储的当前用户的密码, 密码加盐的值,Realm的名称, 即把数据库中的当前的用户, 与用户输入的用户名密码即存储在 UsernamePasswordToken进行比较,如果密码正确,登录成功,密码不正确登录失败.
在这里插入图片描述
在这里插入图片描述
调用自定义Realm的AuthenticationInfo完了之后, 调用RetryLimitCredentialsMatcher类中的doCredentialsMatch方法, 进行密码匹配次数的记录. 并用EhCache作为缓存, 把当前登录的用户名作为key,key的过期时间按照需求设置即可, 把登录的次数作为值.首先通过用户名,获取登录次数,如果登录次数为0, 那么先给当前用户设置一个缓存,登录次数+1,之后判断是否大于限定的登录错误次数,如果超过了限定次数,则抛出异常,用全局的异常拦截器,拦截此异常, 记录登录错误次数的异常, 并封装登录次数过多的提示,给客户端. 具体的代码在下面.

二、Controller层接收登录请求

Shiro的工具类ShiroKit

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;import java.util.List;/*** shiro工具类***/
public class ShiroKit {/*** 名称分隔符*/private static final String NAMES_DELIMETER = ",";/*** 加盐参数*/public final static String HASH_ALGORITHM_NAME = "MD5";/*** 循环次数*/public final static int HASHITERATIONS = 1024;/*** 验证是否同一个账号重新登录的属性,为true代表是重新登录, 初始化为false,代表不是重新登录*/public static boolean ISPEATEDLOGIN =false;/*** shiro密码加密工具类** @param credentials 密码* @param saltSource  密码盐* @return*/public static String md5(String credentials, String saltSource) {ByteSource salt = new Md5Hash(saltSource);return new SimpleHash(HASH_ALGORITHM_NAME, credentials, salt, HASHITERATIONS).toString();}/*** 获取随机盐值** @param length* @return*/public static String getRandomSalt(int length) {return ToolUtil.getRandomString(length);}/*** 获取当前 Subject.* Subject表示单个应用程序用户的状态和安全操作。* 这些操作包括身份验证(登录/注销),授权(访问控制)和会话访问。* 这是Shiro的单用户安全功能的主要机制。** @return Subject*/public static Subject getSubject() {return SecurityUtils.getSubject();}/*** 获取封装的 ShiroUser** @return ShiroUser*/public static ShiroUser getUser() {if (isGuest()) {return null;} else {return (ShiroUser) getSubject().getPrincipals().getPrimaryPrincipal();}}/*** 从shiro获取session*/public static Session getSession() {return getSubject().getSession();}/*** 获取shiro指定的sessionKey*/@SuppressWarnings("unchecked")public static <T> T getSessionAttr(String key) {Session session = getSession();return session != null ? (T) session.getAttribute(key) : null;}/*** 设置shiro指定的sessionKey*/public static void setSessionAttr(String key, Object value) {Session session = getSession();session.setAttribute(key, value);}/*** 移除shiro指定的sessionKey*/public static void removeSessionAttr(String key) {Session session = getSession();if (session != null)session.removeAttribute(key);}/*** 验证当前用户是否属于该角色?,使用时与lacksRole 搭配使用** @param roleName 角色名* @return 属于该角色:true,否则false*/public static boolean hasRole(String roleName) {return getSubject() != null && roleName != null&& roleName.length() > 0 && getSubject().hasRole(roleName);}/*** 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。** @param roleName 角色名* @return 不属于该角色:true,否则false*/public static boolean lacksRole(String roleName) {return !hasRole(roleName);}/*** 验证当前用户是否属于以下任意一个角色。** @param roleNames 角色列表* @return 属于:true,否则false*/public static boolean hasAnyRoles(String roleNames) {boolean hasAnyRole = false;Subject subject = getSubject();if (subject != null && roleNames != null && roleNames.length() > 0) {for (String role : roleNames.split(NAMES_DELIMETER)) {if (subject.hasRole(role.trim())) {hasAnyRole = true;break;}}}return hasAnyRole;}/*** 验证当前用户是否属于以下所有角色。** @param roleNames 角色列表* @return 属于:true,否则false*/public static boolean hasAllRoles(String roleNames) {boolean hasAllRole = true;Subject subject = getSubject();if (subject != null && roleNames != null && roleNames.length() > 0) {for (String role : roleNames.split(NAMES_DELIMETER)) {if (!subject.hasRole(role.trim())) {hasAllRole = false;break;}}}return hasAllRole;}/*** 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用** @param permission 权限名* @return 拥有权限:true,否则false*/public static boolean hasPermission(String permission) {return getSubject() != null && permission != null&& permission.length() > 0&& getSubject().isPermitted(permission);}/*** 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。** @param permission 权限名* @return 拥有权限:true,否则false*/public static boolean lacksPermission(String permission) {return !hasPermission(permission);}/*** 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。与notAuthenticated搭配使用** @return 通过身份验证:true,否则false*/public static boolean isAuthenticated() {return getSubject() != null && getSubject().isAuthenticated();}/*** 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。。** @return 没有通过身份验证:true,否则false*/public static boolean notAuthenticated() {return !isAuthenticated();}/*** 认证通过或已记住的用户。与guset搭配使用。** @return 用户:true,否则 false*/public static boolean isUser() {return getSubject() != null && getSubject().getPrincipal() != null;}/*** 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。用user搭配使用** @return 访客:true,否则false*/public static boolean isGuest() {return !isUser();}/*** 输出当前用户信息,通常为登录帐号信息。** @return 当前用户信息*/public static String principal() {if (getSubject() != null) {Object principal = getSubject().getPrincipal();return principal.toString();}return "";}}
三、自定义的Realm
import cn.stylefeng.roses.core.util.HttpContext;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.utry.govaffairs.core.shiro.service.UserAuthService;
import cn.utry.govaffairs.core.shiro.service.impl.UserAuthServiceServiceImpl;
import cn.utry.govaffairs.modular.system.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class ShiroDbRealm extends AuthorizingRealm {@Autowiredprivate SessionDAO sessionDAO;/*** 登录认证  证明 鉴定*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)throws AuthenticationException {// 获取shirorealm所需数据的Service层UserAuthService shiroFactory = UserAuthServiceServiceImpl.me();//获取Controller层传递的token,包含了前端输入的用户名和密码 一个简单的用户名/密码身份验证令牌UsernamePasswordToken token = (UsernamePasswordToken) authcToken;//获取登录的用户名String username = token.getUsername();//根据前端输入的账号, 去数据库查询用户信息. 此时如果账号不存在(包括逻辑删除)或被冻结,直接抛出异常,终止登录User user = shiroFactory.user(token.getUsername());//进行用户的验证ShiroUser shiroUser = shiroFactory.shiroUser(user);// 获取需要登录的用户在数据库中存储的加盐的密码String credentials = user.getPassword();//  获取需要登录的用户在数据库中存储的密码的盐值String source = user.getSalt();ByteSource credentialsSalt = new Md5Hash(source);// 创建SimpleAuthenticationInfo 返回给shiro的安全管理器去比较当前登录用户输入的密码,与数据库中存储的加盐的密码是否一致// 即在登录的Controller层 UsernamePasswordToken 中存储了当前输入的用户名与密码, 与此SimpleAuthenticationInfo 进行比较// 如果密码一致,代表登录成功, 密码不一致,则报密码错误的异常return new SimpleAuthenticationInfo(shiroUser, credentials, credentialsSalt, realmName);}/*** 权限认证  授权,认可*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}
四、密码验证器增加登录次数校验功能
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;/*** 验证器,增加了登录次数校验功能*/public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher {/*** 密码输入错误次数就被冻结*/private Integer errorPasswordTimes=5;private Cache<String, AtomicInteger> passwordRetryCache;/*** 构造方法 创建对象,传入缓存的管理器* @param cacheManager*/public RetryLimitCredentialsMatcher(CacheManager cacheManager) {passwordRetryCache = cacheManager.getCache("passwordRetryCache");}/*** 方法名: doCredentialsMatch* 方法描述: 用户登录错误次数方法.* 修改日期: 2019/2/26 20:19* @param token* @param info* @return boolean* @throws*/@Overridepublic boolean doCredentialsMatch(AuthenticationToken token,AuthenticationInfo info) {String username = (String) token.getPrincipal();Set<String> keys = passwordRetryCache.keys();// retry count + 1AtomicInteger retryCount = passwordRetryCache.get(username);if (retryCount == null) {retryCount = new AtomicInteger(0);passwordRetryCache.put(username, retryCount);}if (retryCount.incrementAndGet() > errorPasswordTimes) {// if retry count > 5 throwthrow new ExcessiveAttemptsException();}boolean matches = super.doCredentialsMatch(token, info);if (matches) {// clear retry countpasswordRetryCache.remove(username);}return matches;}
}
五、ShiroConfig的配置类

在此配置类中, 要注意的是把ShiroDbRealm的bean中要调用set方法注入retryLimitCredentialsMatcher,否则密码错误次数的校验不会生效.

@Configuration
public class ShiroConfig {/*** Shiro生命周期处理器:* 用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调(例如:UserRealm)* 在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调(例如:DefaultSecurityManager)*/@Beanpublic LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** 方法名: getDefaultAdvisorAutoProxyCreator* 方法描述:  开启Shiro的注解模式* 修改日期: 2019/2/25 16:03* @param* @return org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator* @author taohongchao* @throws*/@Beanpublic DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();autoProxyCreator.setProxyTargetClass(true);return autoProxyCreator;}/*** 安全管理器*/@Beanpublic DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager,CacheManager cacheShiroManager,SessionManager sessionManager,RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//把自定义的Realm注入安全管理器中securityManager.setRealm(this.shiroDbRealm(retryLimitCredentialsMatcher));securityManager.setCacheManager(cacheShiroManager);securityManager.setRememberMeManager(rememberMeManager);securityManager.setSessionManager(sessionManager);return securityManager;}/*** 缓存管理器 使用Ehcache实现*/@Beanpublic CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) {EhCacheManager ehCacheManager = new EhCacheManager();ehCacheManager.setCacheManager(ehcache.getObject());ehCacheManager.setCacheManagerConfigFile("ehcache.xml");return ehCacheManager;}@Beanpublic RetryLimitCredentialsMatcher getRetryLimit(CacheManager cacheManager){RetryLimitCredentialsMatcher retryLimitCredentialsMatcher = new RetryLimitCredentialsMatcher(cacheManager);retryLimitCredentialsMatcher.setHashAlgorithmName(ShiroKit.HASH_ALGORITHM_NAME);retryLimitCredentialsMatcher.setHashIterations(ShiroKit.HASHITERATIONS);retryLimitCredentialsMatcher.setStoredCredentialsHexEncoded(true);return retryLimitCredentialsMatcher;}/*** 项目自定义的Realm*/@Beanpublic ShiroDbRealm shiroDbRealm(RetryLimitCredentialsMatcher retryLimitCredentialsMatcher) {ShiroDbRealm shiroDbRealm = new ShiroDbRealm();shiroDbRealm.setCredentialsMatcher(retryLimitCredentialsMatcher);return shiroDbRealm;}
}
六、EhCache 的配置

EhCache.xml中的配置, 其中设置了名称为passwordRetryCache的缓存,用于冻结密码输入错误次数多过的缓存.


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd"updateCheck="false" monitoring="autodetect"dynamicConfig="true" ><diskStore path="java.io.tmpdir/ehcache"/><defaultCachemaxElementsInMemory="50000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="3600"overflowToDisk="true"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!-- 登录记录缓存 锁定10分钟 --><cache name="passwordRetryCache"eternal="false"timeToIdleSeconds="600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"maxEntriesLocalHeap="0"></cache></ehcache>

EhCacheConfig的配置类

import net.sf.ehcache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;/*** ehcache配置** @author* @date 2017-05-20 23:11*/
@Configuration
@EnableCaching
public class EhCacheConfig {/*** EhCache的配置*/@Beanpublic EhCacheCacheManager cacheManager(CacheManager cacheManager) {return new EhCacheCacheManager(cacheManager);}/*** EhCache的配置*/@Beanpublic EhCacheManagerFactoryBean ehcache() {EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));return ehCacheManagerFactoryBean;}
}
七、全局异常的配置

当密码输入错误次数过多时,抛出ExcessiveAttemptsException异常,被此异常拦截器拦截


@ControllerAdvice
@Order(-1)
public class GlobalExceptionHandler {/*** 方法名: excessiveAttemptsException* 方法描述:  登录错误次数过多异常	* @throws*/@ExceptionHandler(ExcessiveAttemptsException.class)@ResponseStatus(HttpStatus.UNAUTHORIZED)public String excessiveAttemptsException(ExcessiveAttemptsException e, Model model) {String username = getRequest().getParameter("username");LogManager.me().executeLog(LogTaskFactory.loginLog(username, "登录错误次数超过五次", getIp()));model.addAttribute("tips", "登录错误次数超过五次,请十分钟后登录!");return "/login.html";}
}

最终的效果如图所示
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux putty 字体,putty修改字体配色

先看效果步骤&#xff1a;1. 打开Windows注册表编辑器开始 -> regedit2. 找到putty默认session所在位置HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\Default%20Settings3. 右键导出修改# 字体(monaco字体不错&#xff0c;如效果图)"Font""Consol…

90后ACE成长记——从偏居一隅小城里走出的核心技术人

《ACE成长记》栏目说明 名词解释&#xff1a; 阿里云工程师&#xff0c;简称 ACE &#xff08;Alibaba Cloud Engineer&#xff09;&#xff0c;代表云计算的爱好者&#xff0c;是最“王牌”&#xff08;ACE&#xff09;的一群开发者&#xff0c;也是未来的MVP。 ACE 是遍布在…

阿里开发者招聘节 | 面试题01:如何实现一个高效的单向链表逆序输出?

面试&#xff0c;如同玩一场饥饿游戏&#xff1a;既要对环境了然于胸&#xff0c;又要对自身心知肚明。发现一个好工作不容易&#xff0c;但成功应聘又会面临一系列的挑战。 为帮助开发者们提升面试技能、有机会入职阿里&#xff0c;云栖社区特别制作了这个专辑——阿里巴巴资…

从Kubernetes安全地访问AWS服务,告诉你多云场景下如何管理云凭据!

作者| Alexey Ledenev翻译 | 天道酬勤&#xff0c;责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;随着企业与各种云提供商合作&#xff0c;多云场景已经变得十分常见。在谷歌Kubernetes引擎&#xff08;GKE&#xff09;上运行的应用程序需要访…

MSSQL-最佳实践-Always Encrypted

摘要 在SQL Server安全系列专题月报分享中&#xff0c;往期我们已经陆续分享了&#xff1a;如何使用对称密钥实现SQL Server列加密技术、使用非对称密钥实现SQL Server列加密、使用混合密钥实现SQL Server列加密技术、列加密技术带来的查询性能问题以及相应解决方案、行级别安…

java实现对文件加解密操作

源文件&#xff1a; 加密后的文件&#xff1a; 解密后的文件&#xff1a; package com.gblfy.test;import java.io.*;/*** java 实现对文件加解密的方法** author gblfy* date 2020-12-08*/ public class IOSercet {//获取系统类型private static String OS System.getPro…

如何在工作中快速成长?致工程师的10个简单技巧

阿里妹导读&#xff1a;阿里有句非常经典的土话&#xff0c;“今天的最好表现&#xff0c;是明天的最低要求。”如何挖掘潜能、发现更好的自己&#xff1f;今天&#xff0c;阿里巴巴高级无线开发专家江建明将认知升级的方法总结出来&#xff0c;帮助你获得快速成长的秘诀&#…

1 手写第一个Win32窗口程序

1 基础概念 什么是窗口&#xff1f; 答&#xff1a;窗口就是屏幕上的一片区域&#xff0c;接受用户的输入&#xff0c;显示程序的输出。可以包含标题栏、菜单栏、工具栏以及控件等。什么是句柄&#xff1f; 答&#xff1a; 作为一种管理和操作系统资源的机制&#xff0c;提供了…

解析云原生与云计算本质区别,别再傻傻分不清楚了!

来源| comparethecloud翻译 | 天道酬勤&#xff0c;责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;云应用程序是热门话题。很多时候&#xff0c;我们会遇到像云原生应用程序和云计算应用程序这样的术语。首先&#xff0c;很少有人同时使用这两…

阿里开发者招聘节 | 面试题02-04:给定一个二叉搜索树(BST),找到树中第K小的节点

为帮助开发者们提升面试技能、有机会入职阿里&#xff0c;云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出&#xff08;面试题官方参考答案将在专辑结束后统一汇总分享&#xff0c;点此进入答题并围观他…

确认!别再相信Python了! 程序员:就你敢说...

程序员你有没有感觉到&#xff0c;Python最近已经刷屏到爆炸了&#xff1f;细分析Python之所以刷屏&#xff0c;主要是因为人红是非多&#xff0c;在编程界它是一种特殊的存在&#xff0c;有人认为&#xff0c;只有用Python才能优雅写代码&#xff0c;提高代码效率&#xff1b;…

云原生的新思考,为什么容器已经无处不在了

4月24日&#xff0c;中国信息通信研究院主办的首届云原生产业大会在北京举行&#xff0c;在《云原生数字引领未来》的主题演讲中&#xff0c;阿里云容器服务总监易立表示&#xff1a;“云原生不但可以很好的支持互联网应用&#xff0c;也在深刻影响着新的计算架构、新的智能数据…

走近科学,探究阿里闲鱼团队通过数据提升Flutter体验的真相

背景 闲鱼客户端的flutter页面已经服务上亿级用户&#xff0c;这个时候Flutter页面的用户体验尤其重要&#xff0c;完善Flutter性能稳定性监控体系&#xff0c;可以及早发现线上性能问题&#xff0c;也可以作为用户体验提升的衡量标准。那么Flutter的性能到底如何&#xff1f;…

阿里3篇技术论文入选国际顶级会议FAST2020,全球第一!

2月26日&#xff0c;存储行业顶级国际会议FAST2020&#xff08;18th USENIX Conference on File and Storage Technologies&#xff09;在美国圣克拉拉举行&#xff0c;大会公开论文名单显示&#xff0c;阿里巴巴3篇第一作者论文入选&#xff0c;是全球入选数最多的企业。 FAS…

oracle11g linux 日期格式设置

下面的过程把oracle 的日期格式设置成 yyyy-mm-dd hh24:mi:ss(1) 使用 oracle 用户登录(2) 在.bash_profile里增加以下两条环境变量export NLS_LANGamerican_america.ZHS16GBK export NLS_DATE_FORMAT"YYYY-MM-DD HH24:MI:SS" (3) 执行一下"source .bash_profil…

一份还热乎的蚂蚁金服面经(已拿Offer)!附答案!!

本文来自我的知识星球的球友投稿&#xff0c;他在最近的校招中拿到了蚂蚁金服的实习生Offer&#xff0c;整体思路和面试题目由作者——泽林提供&#xff0c;部分答案由Hollis整理自知识星球《Hollis和他的朋友们》中「直面Java」板块。 经历了漫长一个月的等待&#xff0c;终于…

linux RssFile什么含义,什么是RSS

导读RSS 指 Really Simple Syndication(真正简易联合),RSS 的 元素可描述 RSS feed。RSS 元素RSS 的 元素可描述 RSS feed。请看下面这个 RSS 文档&#xff1a;<?xml version"1.0"encoding"UTF-8"?>菜鸟教程首页http://www.runoob.com免费编程教程…

linux CPU、内存、I/O、磁盘等监控统一解决方案

文章目录一、效果图二、软件安装配置2.1. nmon安装2.2. 权限赋予2.3. 脚本制作2.4. 脚本运行三、解析监控文件3.1. 监控文件下载3.2. 解析监控文件3.3. 监控指标总览补充内存计算方式需求背景: 性能测试过程中监控服务器健康(CPU、内存、I/O、磁盘)指标的状态 一、效果图 二、软…

数据科学家常见的5个SQL面试问题

作者 | Alexei Ledenev翻译 | 天道酬勤&#xff0c;责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;在任何以数据为中心的工作中&#xff0c;对SQL有深刻的理解都是成功的关键&#xff0c;尽管这不是工作中最有趣的部分。事实上&#xff0c;除了…

c语言程序滞留,c语言有个可以使程序延时的语句是什么?

满意答案hsgfzdg99推荐于 2017.09.11采纳率&#xff1a;57% 等级&#xff1a;9已帮助&#xff1a;1169人Sleep函数:功 能: 执行挂起一段时间  用 法: unsigned sleep(unsigned seconds);  注意:  在VC中使用带上头文件#include  在VC中,Sleep中的第一个英文字符为大写的…