我的shiro之旅: 十四 shiro 自动登录

Shiro免密登录 目录 1.千篇一律 2.点睛之笔 所做项目与第三方合作,系统间存在接口调用,需要做授权登录。我们的项目整体使用SSM框架,认证登陆采用了shiro框架,密码在数据库中经过盐值(salt)+Md5加密,外部无法获知密码明文,导致无法验证通过,所以想到了免密登录的方式解决。 在网上查阅了一些贴子,套路基本一样,照搬了全部代码,发现在强转AuthenticationToken为自定义Tok... 阅读详情

博客已移至 http://blog.gogl.top

shiro有几种状态,其中包括guest,user,authenticated。guest就是游客,authenticated就是认证后的用户,而user是介于两者之前。user并不代表用户已经成功认证,当用户上次登录时选择rememberMe,下次用户再访问时就是user状态。登录时选择rememberMe,shiro会通过一种加密方式将principal(我们理解为用户名)加密保存到cookie中。shiro可以通过这个cookie解密得到principal。所以当状态为user时,虽然并不代表用户已经通过认证,但我们却可以通过Subject拿到用户名。先贴出代码:

 

       public void autoLogin(HttpServletRequest request, HttpServletResponse response) {

		Subject subject = SecurityUtils.getSubject();
		if(subject.isRemembered()){
			String username = ShiroSecurityHelper.getCurrentUsername();
			LOG.info("用户【{}】自动登录----{}", username,TimeHelper.getCurrentTime());
			User user = userService.getByUsername(username);
			baseLogin(user, request, response);
			ShiroAuthorizationHelper.clearAuthorizationInfo(username); // 用户是自动登录,首先清一下用户权限缓存,让重新加载
		}
	}

 

 

public void baseLogin(User user, HttpServletRequest request, HttpServletResponse response) {  
          
    try {  
        Subject subject= SecurityUtils.getSubject();  
        if (subject.isAuthenticated()) {  
            return;  
        }  
        //如果用户已登录,先踢出  
        ShiroSecurityHelper.kickOutUser(user.getUsername());  
              
        boolean rememberMe = ServletRequestUtils.getBooleanParameter(request, "rememberMe", false);  
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), rememberMe);  
        subject.login(token); // 登录  
    } catch (Exception e) {  
        //做一些异常处理  
    }finally{  
        ShiroAuthorizationHelper.clearAuthorizationInfo(sessionUser.getUsername());  
    }  
}  


ShiroAuthorizationHelper在文章我的shiro之旅: 九 shiro 清理缓存的权限信息有介绍。我们来看看DelegatingSubject类的isRemembered()方法的实现。

 

    public boolean isRemembered() {
        PrincipalCollection principals = getPrincipals();
        return principals != null && !principals.isEmpty() && !isAuthenticated();
    }

当能拿到principals和用户没认证的时候,这个方法才返回true,principals可以通过cookie解密得到。如果用户是认证状态的,这个方法将返回false。

如此看来,shiro的自动登录实现还是比较简单。

securityManager有个rememberMeManager,用来管理rememberMe的,默认情况下,这个cookie会保存一年时间,我们可以看一下RememberMeManager接口的实现类org.apache.shiro.web.mgt.CookieRememberMeManager的源码:

 

public class CookieRememberMeManager extends AbstractRememberMeManager {

    //TODO - complete JavaDoc

    private static transient final Logger log = LoggerFactory.getLogger(CookieRememberMeManager.class);

    /**
     * The default name of the underlying rememberMe cookie which is {@code rememberMe}.
     */
    public static final String DEFAULT_REMEMBER_ME_COOKIE_NAME = "rememberMe";

    private Cookie cookie;

    /**
     * Constructs a new {@code CookieRememberMeManager} with a default {@code rememberMe} cookie template.
     */
    public CookieRememberMeManager() {
        Cookie cookie = new SimpleCookie(DEFAULT_REMEMBER_ME_COOKIE_NAME);
        cookie.setHttpOnly(true);
        //One year should be long enough - most sites won't object to requiring a user to log in if they haven't visited
        //in a year:
        cookie.setMaxAge(Cookie.ONE_YEAR);
        this.cookie = cookie;
    }

    public Cookie getCookie() {
        return cookie;
    }

 
    @SuppressWarnings({"UnusedDeclaration"})
    public void setCookie(Cookie cookie) {
        this.cookie = cookie;
    }
    protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {

        if (!WebUtils.isHttp(subject)) {
            if (log.isDebugEnabled()) {
                String msg = "Subject argument is not an HTTP-aware instance.  This is required to obtain a servlet " +
                        "request and response in order to set the rememberMe cookie. Returning immediately and " +
                        "ignoring rememberMe operation.";
                log.debug(msg);
            }
            return;
        }


        HttpServletRequest request = WebUtils.getHttpRequest(subject);
        HttpServletResponse response = WebUtils.getHttpResponse(subject);

        //base 64 encode it and store as a cookie:
        String base64 = Base64.encodeToString(serialized);

        Cookie template = getCookie(); //the class attribute is really a template for the outgoing cookies
        Cookie cookie = new SimpleCookie(template);
        cookie.setValue(base64);
        cookie.saveTo(request, response);
    }

    private boolean isIdentityRemoved(WebSubjectContext subjectContext) {
        ServletRequest request = subjectContext.resolveServletRequest();
        if (request != null) {
            Boolean removed = (Boolean) request.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY);
            return removed != null && removed;
        }
        return false;
    }
    protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {

        if (!WebUtils.isHttp(subjectContext)) {
            if (log.isDebugEnabled()) {
                String msg = "SubjectContext argument is not an HTTP-aware instance.  This is required to obtain a " +
                        "servlet request and response in order to retrieve the rememberMe cookie. Returning " +
                        "immediately and ignoring rememberMe operation.";
                log.debug(msg);
            }
            return null;
        }

        WebSubjectContext wsc = (WebSubjectContext) subjectContext;
        if (isIdentityRemoved(wsc)) {
            return null;
        }

        HttpServletRequest request = WebUtils.getHttpRequest(wsc);
        HttpServletResponse response = WebUtils.getHttpResponse(wsc);

        String base64 = getCookie().readValue(request, response);
        // Browsers do not always remove cookies immediately (SHIRO-183)
        // ignore cookies that are scheduled for removal
        if (Cookie.DELETED_COOKIE_VALUE.equals(base64)) return null;

        if (base64 != null) {
            base64 = ensurePadding(base64);
            if (log.isTraceEnabled()) {
                log.trace("Acquired Base64 encoded identity [" + base64 + "]");
            }
            byte[] decoded = Base64.decode(base64);
            if (log.isTraceEnabled()) {
                log.trace("Base64 decoded byte array length: " + (decoded != null ? decoded.length : 0) + " bytes.");
            }
            return decoded;
        } else {
            //no cookie set - new site visitor?
            return null;
        }
    }
    private String ensurePadding(String base64) {
        int length = base64.length();
        if (length % 4 != 0) {
            StringBuilder sb = new StringBuilder(base64);
            for (int i = 0; i < length % 4; ++i) {
                sb.append('=');
            }
            base64 = sb.toString();
        }
        return base64;
    }
    protected void forgetIdentity(Subject subject) {
        if (WebUtils.isHttp(subject)) {
            HttpServletRequest request = WebUtils.getHttpRequest(subject);
            HttpServletResponse response = WebUtils.getHttpResponse(subject);
            forgetIdentity(request, response);
        }
    }

    public void forgetIdentity(SubjectContext subjectContext) {
        if (WebUtils.isHttp(subjectContext)) {
            HttpServletRequest request = WebUtils.getHttpRequest(subjectContext);
            HttpServletResponse response = WebUtils.getHttpResponse(subjectContext);
            forgetIdentity(request, response);
        }
    }
    private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
        getCookie().removeFrom(request, response);
    }
}

从构造器中看到cookie.setMaxAge(Cookie.ONE_YEAR);设置cookie的有效时间为一年。也许,这对我们来说会有点长,我们可以更改这些设置。配置如下:

 

 

	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="shiroRealm" />
		<!-- <property name="sessionMode" value="native"/> -->
		<property name="cacheManager" ref="shiroCacheManager"/>
		<property name="sessionManager" ref="shiroSessionManager"/>
		<property name="rememberMeManager.cookie.name" value="rememberMe"/>
		<property name="rememberMeManager.cookie.domain" value=".xxx.com"/>
		<property name="rememberMeManager.cookie.path" value="/"/>
		<property name="rememberMeManager.cookie.maxAge" value="604800"/> <!-- 7天有效期 -->
		<!-- <property name="subjectDAO" ref="subjectDAO"/> -->
	</bean>

当然,我们也可以实现自己的rememberMeManager。

 

 

shiro免密码登录 在实际开发中,一般我们使用shiro进行用户密码登录,有时候面对一些常见的需求,不得不再已有的框架上进行修改,比如说,增加一种使用手机验证码登录的登录方式。这时候,我们可以根据已有的框架,对其稍微修改一下便可满足需求。 public class ShiroDBRealm extends AuthorizingRealm{ private static final String classNam 阅读详情

相关推荐

shiro实现免密登录,解决三方登录问题

问题: 之前在一个项目中,需要实现短信快捷登录,当输入手机号获取验证码且验证码正确时,通过数据库查询出用户,而由于使用了shiro对密码进行了加密,导致查询出来的用户密码时加密的,不能够进行登录。 解决办法: 1.定义一个枚举代码如下 public enum LoginType { PASSWORD(&quot;password&quot;), // 密码登录 NOPASSWD(&quot;nopassword...

知的IT成长之路 1万+

4.SpringBoot+Shiro免密登录

一、查看原有的代码首先我们看一下Shiro原有的账号密码登录关键代码,分析一下该如何改造, 从这两行代码看出,我们需要重写一个获得Token的方法。二、改造1.新建一个枚举类,这个也可以不建立,因为我这边的系统免密登录和账号密码登录的情况有存在,所以我加了一个枚举类进行判断,用户具体执行哪一个登录方法。枚举类具体代码如下: 2.新建自定义的UserRealem类继承AuthorizingRealm 3.修改ShiroUser 类的代码 4.修改ShiroDBRealm类的代码 5.修改L

qq_27860623的博客 2954

spring集成shiro实现权限认证和自动登录

个站链接:http://www.legolas94.top/article/get/1003 首先在登录入口类中得到shiro的Subject然后调用 UsernamePasswordToken token = new UsernamePasswordToken(phone, password); 创建用户名/密码身份验证Token。然后调用subject.login(token);此时Secur...

KGLegolas的博客 1096

Shiro免密码登录

1.shiro的配置文件里面有一个是这需要一个继承HashedCredentialsMatcher的子类,重写doCredentialsMatch方法。最近遇到的需求,实现手机号+验证码登录,验证码能够通过查数据库校验,但是密码是加密过的对不上,需要免密登录,所以写一下帮助后人。2.自定义一个token,继承自UsernamePasswordToken,添加一个标识符表名是否免密登录。4.回到第一步 重写方法的第一行 直接强转 token 获取标识符 如果为免密登录 直接返回true。

m0_67401153的博客 2956

shiro禁止多点登录或重复登录

原文地址 目的:每个用户只允许一个session可用,在redis中也只能有一条session记录 为演示直接在Controller层进行控制(我也不是很清楚应该在哪里进行控制,哈哈哈) 思路:shiro认证通过之后向session中保存当前登录的账号(唯一识别),获取redis 中存的所有session,依据上次登录向session保存的信息找到上一次存的session,先删除redis中的...

iLeeHan 1552

SpringBoot集成shiro认证,实现Shiro认证的登录操作

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习已经将知识体系整理好(源码,笔记,PPT,学习视频)《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!” />我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习已经将知识体系整理好(源码,笔记,PPT,学习视频)[外链图片转存中…(img-Z7OhkLXx-1713323885625)]

2303_77877769的博客 837

Shiro 实现免密登陆

* 1.账号密码登陆(password)* 2.免密登陆(nopassword)*

web17508858916的博客 1075

SpringBoot整合Shiro后实现免密登录

SpringBoot整合Shiro后实现免密登录 1,说明一下步骤,需要在原来基础新增三个文件 2,新增CustomToken,重写UsernamePasswordToken免密登录调用方法和密码登录调用方法都在里面。 3,新增MyRetryLimitCredentialsMatcher,重写HashedCredentialsMatcher,主要是判定登录是否是免密登录。 4,新增LoginType,登录类型枚举 5,修改ShiroConfig文件,即Shiro配置文件,主要关注:57,63,65-90行 原文链接:https://blog.youkuaiyun.com/zlxls/article/details/105455375

springboot(十四):springboot整合shiro-登录认证和权限管理

这篇文章我们来学习如何使用Spring Boot集成Apache Shiro。安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求。在Java领域一般有Spring Security、Apache Shiro等安全框架,但是由于Spring Security过于庞大和复杂,大多数公司会选择Apache Shiro来使用,这篇文章会先介绍一下Apache Shiro,在结合Spri

纯洁的微笑 9万+

shiro登陆身份认证和权限管理 密码加密

shiro登陆,shiro登陆身份认证和权限管理 密码加密。自己写的demo。实用。希望大家多多支持。谢谢大家

Day01 Geant4学习

​ 用来记录粒子在每个step中的信息的,例如位置,能量,动量.例如,假设每一个粒子都有一个属于自己的id,会记录自己的轨迹状态信息就是track,当他发生反应时,就会产生新的id。​ 最终在新建的build文件夹中的vis.mac文件中设置,是自带的,如果有更高的需求可以自己去更改,但是一般都是写好的,设置好了图形界面的一些东西,呈现的自己建模的图形界面多大,需不需要网格什么的。从反应到结束的过程,其中也包括它产生的刺激粒子的反应到结束的过程,成为一个事件event。

LXS_357的博客 933

我的shiro之旅: 十五 shiro 登录成功后,跳转到登录前的页面

博客已移至 http://blog.gogl.top 很多时候,我们需要做到,当用户登录成功后,跳转回登录前的页面。如果用户是点击"登录"链接去到登录页面进行登录的,我们很容易跟踪用户的登录前的页面。比如,在"登录"链接后加一个url参数,如:http://www.xxx.com/login.html?url=http://www.xxx.com/xx.html,这个url就是当前页面。用户浏览...

Dylan的博文 3万+

手把手教你搞定CAC会议投稿:从LaTeX模板到PDF eXpress避坑全流程

本文详细解析CAC会议投稿全流程,重点介绍LaTeX模板调整、Turnitin查重技巧及PDF eXpress校验避坑指南。通过实战案例和代码示例,帮助研究者高效完成IEEE格式论文投稿,避免常见技术性失误,提升投稿成功率。

weixin_29969209的博客 397

我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)

博客已移至 http://blog.gogl.top 看了一下官网,没有找到关于如何控制同一用户只能一处登录的介绍,网上也没有找到相关的文章。可能有些人会记录用户的登录信息,然后达到踢出用户的效果。这里介绍一个更简单的方法。 如果我们跟shiro的源码,我们可以看到。当用户登录成功后,shiro会把用户名放到session的attribute中,key为DefaultSubjectContex...

Dylan的博文 2万+

STK传感器配置全攻略:从光学到雷达的7种视场类型详解(附避坑指南)

本文详细解析了STK软件中传感器的7种视场类型,从基础的Simple Conic、Complex Conic到高级的SAR与EOIR,提供了完整的配置步骤与实战避坑指南。重点阐述了雷达、光学等不同物理设备的建模选择逻辑,并针对常见的“No Access”等报错问题给出了系统性的排查方案,帮助工程师高效完成卫星系统设计与任务分析。

weixin_29232507的博客 228

Android 以太网802.1x 配置

802.1X认证网络配置摘要:本文介绍了通过wpa_supplicant.conf文件配置802.1X企业网络认证的两种方法:PEAP-MSCHAPv2方式和TLS方式。PEAP方式需设置SSID、用户名、密码,可选择是否验证CA证书;TLS方式则需要配置客户端证书、私钥及CA证书路径。文件配置完成后需设置权限并重启设备。最后提出如何验证802.1X配置是否生效的问题,但未给出具体验证方法。该配置适用于需要802.1X认证的企业网络环境。

zhaoyufei133的博客 458

Shiro自动登录

第一步 :配置spring.xml,配置cookieRememberMeManager <!--创建SecurityManager对象--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name=...

lmchhh的博客 509

FFmpeg魔改指南:让RTMP协议完美兼容H265的三种方法(含SRS适配技巧)

本文详细介绍了三种让RTMP协议兼容H265编码的FFmpeg魔改方案,包括基于官方补丁的标准改造、Intel的SVT-HEVC集成方案以及金山云的自定义扩展方案。文章重点解析了各方案的实现原理与适配技巧,并提供了在SRS 6.0服务器上进行深度配置和性能调优的完整实战指南,帮助开发者解决H265推流至传统RTMP服务器的兼容性问题。

weixin_29290947的博客 195

Shiro框架:Shiro用户登录认证流程源码解析

​Shiro作为一款比较流行的登录认证、访问控制安全框架,被广泛应用在程序员社区;Shiro登录认证、访问控制、Session管理等流程内部都是委托给SecurityManager安全管理器来完成的,SecurityManager安全管理器上篇文章已经进行了详细解析,详见:Shiro框架:Shiro SecurityManager安全管理器解析-优快云博客,在此基础上,本篇文章继续对Shiro关联链路处理流程之一---登录认证流程进行解析;

博客园 2781

Codex 100个真实案例 - 用AI自动生成API测试用例(接口测试全覆盖)

API 测试是保障后端质量的关键环节,但手写测试用例既枯燥又容易遗漏。本案例将展示如何用 Codex 从 Swagger/OpenAPI 规范文档自动生成 pytest 测试用例——包括正常流程测试、边界值测试、异常参数测试、性能压力测试,还能自动生成 Mock 数据和精美的 HTML 测试报告。全程自然语言驱动,让 API 测试覆盖率从 0 飙到 90%+!

yueyeguzhuo的专栏 271

【Shiro】Springboot整合Shiro实现登录和注册

【Shiro】Springboot整合Shiro实现登录和注册简单了解Shiro基本概念内部结构框架JPARealm:通过 JPA 进行验证的 RealmShiro 配置注册登录退出登录拦截器判断是否登录前台判断是否登录 简单了解Shiro 基本概念 Subject:主体,代表当前‘用户’ 。这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽...

weixin_44823875的博客 2526

保边滤波之Mean shift filter

保边滤波之Mean shift filter 目录 保边滤波之Mean shift filter 一、算法原理 二、练手实现的算法代码如下: 三、实现结果 一、算法原理 在OpenCV中,meanshift filter函数为 p...

大熊 1561

Shiro登录的使用以及原理(一)

好久没写博客了,这段时间对最近项目做个总结,先从登入下手,话不多说直奔主题,Shiro的登录使用以及原理。 一、Shiro主要作用 shiro主要的作用就是实现用户登录(认证,授权,加密等),用户登录后的用户信息存储(缓存),用户登出等。 二、登录的使用 在使用登录的时候,最常见的一串代码就是获取Subject,然后对Token进行login(); // 得到subject然后对创建用户名/密码身份验证 Subject subject = SecurityUtils.ge...

大鹏的博客 3321

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

上一篇: 我的shiro之旅: 十三 shiro 用户的登录与退出
下一篇: 我的shiro之旅: 十五 shiro 登录成功后,跳转到登录前的页面
LHacker
博客等级 码龄17年 162粉丝 24原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值