精华内容
下载资源
问答
  • shiro实现APP保持登录状态,以及web统一登录认证和权限管理,会话保持在web和APP之间。转载:https://blog.csdn.net/gaofeihu_/article/details/79447922

    shiro实现APP保持登录状态,以及web统一登录认证和权限管理,会话保持在web和APP之间。

    转载:https://blog.csdn.net/gaofeihu_/article/details/79447922

    展开全文
  • web统一登录验证

    2017-10-27 15:10:29
    //从web.xml读取配置 String[] uriArrays = noUri.split(";"); for(String uri: uriArrays){ uriLists.add(uri); } } public void doFilter(ServletRequest request, ServletResponse response, ...
    /**
     * Servlet Filter implementation class LoginFileter
     */
    public class LoginFileter implements Filter {
    	private List<String> uriLists = new ArrayList<>();
    	public void init(FilterConfig fConfig) throws ServletException {
    		System.out.println("过滤器启动");
    		String noUri = fConfig.getInitParameter("noUri");  //从web.xml读取配置
    		String[] uriArrays = noUri.split(";"); 
    		for(String uri: uriArrays){
    			uriLists.add(uri);
    		}
    	}
    
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		System.out.println("过滤器执行");
    		HttpServletRequest servletrequest = (HttpServletRequest) request;
    		HttpServletResponse ServletResponse = (HttpServletResponse) response;
    		HttpSession session = servletrequest.getSession();
    		String uri = servletrequest.getRequestURI(); //获取地址
    		System.out.println(uri);
    		//不需要登录验证处理
    				if(passLoginValidate(uri) == true){
    					chain.doFilter(request, response); //直接放行
    					return;
    				}
    		String user = (String) session.getAttribute("username"); // 获取用户名密码
    		if (user == null || user.equals("")) { // 如果没有登录就跳转到登录界面
    			System.out.println("未登录账号");
    			ServletResponse.sendRedirect("/IntegralManager_v1.0/jsp/login.jsp");
    		} else {
    			System.out.println("登录");
    			chain.doFilter(request, response);
    		}
    	}
    	public void destroy() {
    		System.out.println("过滤器销毁");
    	}
    
    
    	/**
    	 * 请求uri是否需要登录验证
    	 * @return false:需要验证 true:不需要验证
    	 */
    	public boolean passLoginValidate(String uri) {
    		boolean isPass = false;
    		int index = uri.indexOf("?");
    		if (index != -1) {
    			uri = uri.substring(0, index);
    		}
    		for (String u : uriLists) {  
    			if (uri.endsWith(u)) {//不需要登录验证的网页
    				isPass = true;     
    				break;
    			}
    		}
    		return isPass;
    	}
    
    }
    
    
    
    XML配置文件

      <filter>
        <filter-name>AuthenFilter</filter-name>
        <filter-class>com.hst.integraimanager.filter.LoginFileter</filter-class>
        <init-param>
          <param-name>noUri</param-name>
          <param-value>login.jsp;registered.jsp;jpg;gif;css;js;servlet;do</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>AuthenFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>


    展开全文
  • 先说下背景,项目包含一个管理系统(web)和门户网站(web),还有一个手机APP(包括Android和IOS),三个系统共用一个后端,在后端使用shiro进行登录...web和APP可以用shiro统一登录认证吗?可以。假如web和APP都...

    先说下背景,项目包含一个管理系统(web)和门户网站(web),还有一个手机APP(包括Android和IOS),三个系统共用一个后端,在后端使用shiro进行登录认证和权限控制。好的,那么问题来了web和APP都可以用shiro认证吗?两者有什么区别?如果可以,解决方案是什么?看着大家焦急的小眼神,接下来挨个解决上面的问题。

    web和APP可以用shiro统一登录认证吗?

    可以。假如web和APP都使用密码登录的话,那没的说肯定是可以的,因为对于shiro(在此不会介绍shiro详细知识,只介绍本文章必要的)来说,不管是谁登录,用什么登录(用户名密码、验证码),只要通过subject.login(token)中的token告诉shiro,然后在自己定义的Realm里面给出自己的认证字段就可以了,好吧说的云里雾里,看看代码

    // 在自己登录的rest里面写,比如UserRest里面的login方法中,user为传递过来的参数
    Subject currentUser = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword()); 
    // 开始进入shiro的认证流程
    currentUser.login(token);

    上面的代码是开始使用shiro认证,调用subject.login(token)之后就交给shiro去认证了,接下来和我们相关的就是自定认证的Realm了,比如自定义UserRealm

    复制代码
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {  
            //获取基于用户名和密码的令牌  
            //实际上这个token是从UserResource面currentUser.login(token)传过来的  
            //两个token的引用都是一样的
            UsernamePasswordToken token = (UsernamePasswordToken)authcToken;  
            System.out.println("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
            // 从数据库中获取还用户名对应的user
            User user = userService.getByPhoneNum(token.getUsername());  
            if(null != user){  
                AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getPhoneNum(),user.getPassword(), getName());  
                return authcInfo;  
            }else{  
                return null;  
            }
        }  
    复制代码

    再配一张图

    图中描述的是使用shiro进行一个完整的登录过程

    所以由以上代码看出目前我们还没有发现APP和web登录d区别,那么区别是什么呢?

    web和APP登录认证的区别

    好吧,标题不太准确,应该是登录的时候和登陆之后会话保持在web和APP之间的区别,先说登录:

    登录

    APP和PC web所需的设备不同很大程度上决定了两者之间的区别,web一般在PC上浏览,登录的时候使用用户名和密码,如果使用了记住密码就是用cookie认证,web登录有以下情况

    • 第一次登录,使用用户名和密码登录
    • 关闭浏览器、session过期,重新使用密码登录(如果有记住密码功能,可以使用cookie登录)
    • 用户删除cookie或者cookie过期,使用户名和密码登录

    APP在移动设备上查看,第一次登录的时候使用用户名和密码,但是以后如果不是用户主动退出,都应该保持登录状态,这样才会有更好的用户体验,但是不可能一直保留该APP的会话,也不可能把密码保存在本地,所以APP应该以下的过程

    • 第一次登录,使用用户名密码
    • 以后用户打开应用之后,用户不需输入密码系统就可以自动登录
    • 用户主动退出(重装等情况视为主动退出)之后,使用用户名和密码登录

    貌似没有看出什么区别,唯一的不同就是第二点:怎么不用密码登录,web使用的是cookie(由浏览器自动维护的),APP怎么登陆呢?由于APP本地不保存密码,那么也参考web,使用类似cookie的东西,我们叫他token吧,那问题就解决了,APP本地保存token,为了安全性,定期更新token,那再来看看会话的保持。

    会话(session)(保持状态)

    如果用户登录了,怎么保持登录状态呢,web有cookie和session配合解决这个问题,下面先简单说一下我对这两个东西的理解,因为APP会话就是参考这个原理设计的。

    cookie:是由浏览器维护的,每次请求浏览器都会把cookie放在header里面(如果有的话),也可以看做js的可以访问本地存储数据的位置之一(另一个就是local storage)

    session:由于http是无状态的,但是有时候服务器需要把这次请求的数据保存下来留给下一次请求使用,即需要维护连续请求的状态,这个时候服务器就借助cookie,当浏览器发送请求来服务器的时候,服务器会生成一个唯一的值,写到cookie中返回给浏览器,同时生成一个session对象,这样session和cookie值就有了一一对应关系了,浏览下一次访问的时候就会带着这个cookie值,这个时候服务器就会获得cookie的值,然后在自己的缓存里面查找是否存在和该cookie关联的session

     

    因为cookie和session的配合,shiro可以本身很好的支持web的登录和会话保持,对于APP来说也可以借鉴cookie和session的这种实现方式,唯一存在的问题,就是web的cookie是由浏览器维护的,自动将cookie放在header里面,那我们APP只要把服务器返回的cookie放在header里面,每次访问服务器的时候带上就可以了。

     

    免密码登录

    解决了登录和会话保持的问题,还剩一个免密码登陆:

    web:因为一般网页主需要记住7天密码(或者稍微更长)的功能就可以了,可以使用cookie实现,而且shiro也提供了记住密码的功能,在服务器端session不需要保存过长时间

    APP:因为APP免密码登录时间需要较长(在用户不主动退出的时候,应该一直保持登录状态),这样子在服务器端就得把session保存很长时间,给服务器内存和性能上造成较大的挑战,存在的矛盾是:APP需要较长时间的免密码登录,而服务器不能保存过长时间的session,解决办法:

    • APP第一次登录,使用用户名和密码,如果登录成功,将cookie保存在APP本地(比如sharepreference),后台将cookie值保存到user表里面
    • APP访问服务器,APP将cookie添加在heade里面,服务器session依然存在,可以正常访问
    • APP访问服务器,APP将cookie添加在heade里面,服务器session过期,访问失败,由APP自动带着保存在本地的cookie去服务器登录,服务器可以根据cookie和用户名进行登录,这样服务器又有session,会生成新的cookie返回给APP,APP更新本地cookie,又可以正常访问
    • 用户手动退出APP,删除APP本次存储的cookie,下次登录使用用户名和密码登录

    这种方法存在的问题:

    1. cookie保存在APP本地,安全性较低,可以通过加密cookie增加安全性
    2. 每次服务器session失效之后,得由APP再次发起登录请求(虽然用户是不知道的),但是这样本身就会增加访问次数,好在请求数量并不是很大,不过这种方式会使cookie经常更新,反而增加了安全性

    这里给出另外一种实现方式:

    实现自己的SessionDao,将session保存在数据库,这样子的好处是,session不会大量堆积在内存中,就不需要考虑session的过期时间了,对于APP这种需要长期保存session的情况来说,就可以无限期的保存session了,也就不用APP在每次session过期之后重新发送登录请求了。实现方式如下:

    为了使用Hibernate将Session保存到数据库,新建一个SimpleSessionEntity

    复制代码
    package org.lack.entity;
    
    import java.io.Serializable;
    
    import org.apache.shiro.session.mgt.SimpleSession;
    
    import com.phy.em.user.entity.User;
    
    public class SimpleSessionEntity {
    
        private Long id;
        private String cookie;
        private Serializable session;
        
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public Serializable entity() {
            return session;
        }
        public void setSession(Serializable session) {
            this.session = session;
        }
        public String getCookie() {
            return cookie;
        }
        public void setCookie(String cookie) {
            this.cookie = cookie;
        }
        public Serializable getSession() {
            return session;
        }
    }
    复制代码
    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping package="org.lack.entity">
        <class name="SimpleSessionEntity" table="session">
            <!-- 标识 -->
            <id name="id">
                <column name="id"></column>
                <generator class="increment"></generator>
            </id>
            
            <property name="session">
                <column name="session"></column>
            </property>
            
            <property name="cookie">
                <column name="cookie"></column>
            </property>
    
        </class>
    </hibernate-mapping>
    复制代码

    以上贴出来的是SimpleSessionEntity的映射文件,特别要注意的是Hibernate也是支持把对象保存在数据库中的,但是该实体要实现Serializable,在取出来的时候强转为对应的对象即可,所以这里session的类型为Serializable

    新建session缓存的方式的类,这里继承自EnterpriseCacheSessionDAO,可以使用ehcache作为二级缓存,一定要记得实现save、update、readSession、delete方法,特别是save方法只是保存一个基本的session,重要的attribute都是update的,在readSession中从数据库中读取即可

    复制代码
    package org.lack.dao
    
    import java.io.Serializable;
    import java.util.Date;
    import org.apache.log4j.Logger;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.SimpleSession;
    import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
    import org.springframework.transaction.annotation.Transactional;
    import com.phy.em.common.dao.IBaseDao;
    import com.phy.em.common.shiro.entity.SimpleSessionEntity;
    import com.phy.em.user.entity.User;
    public class SessionEntityDao extends EnterpriseCacheSessionDAO {
        
        private IBaseDao<User> baseDao;
        private IBaseDao<SimpleSessionEntity> sessionDao;
        private Logger log = Logger.getLogger(SessionEntityDao.class);
        
        @Override
        public Serializable create(Session session) {
            // 先保存到缓存中
            Serializable cookie = super.create(session);
            // 新建一个SimpleSessionEntity,然后保存到数据库
            SimpleSessionEntity entity = new SimpleSessionEntity();
            entity.setSession((SimpleSession)session);
            entity.setCookie(cookie.toString());
            sessionDao.save(entity);
            
            return cookie;
        }
        
        @Override
        public void update(Session session) throws UnknownSessionException {
            super.update(session);
            SimpleSessionEntity entity = getEntity(session.getId());
            if(entity != null){
                entity.setSession((SimpleSession)session);    
                sessionDao.update(entity);
            }        
        }
        
        @Override
        public Session readSession(Serializable sessionId) throws UnknownSessionException {
            Session session = null;
            
            try{
                session = super.readSession(sessionId);
            } catch(Exception e){
                
            }
            
            // 如果session已经被删除,则从数据库中查询session
            if(session == null){
                SimpleSessionEntity entity = getEntity(sessionId);
                if(entity != null){
                    session = (Session) entity.getSession();    
                } 
            }
         // 如果是APP则更新lastAccessTime
           User user = getUser(sessionId);
            if(user != null){
              // 如果该用户是APP用户(user不为空说明就是),则判断session是否过期,如果过期则修改最后访问时间
              ((SimpleSession)session).setLastAccessTime(new Date());
            }

         return session; } @Override public void delete(Session session) { super.delete(session); } private User getUser(Serializable sessionId){ String hql = "from User user where user.cookie ='" + sessionId + "'"; return baseDao.findUniqueByHQL(hql); } private SimpleSessionEntity getEntity(Serializable sessionId){ String hql = "from SimpleSessionEntity entity where entity.cookie ='" + sessionId + "'"; return sessionDao.findUniqueByHQL(hql); } private boolean isExpire(Session session){ long timeout = session.getTimeout(); long lastTime = session.getLastAccessTime().getTime(); long current = new Date().getTime(); if((lastTime + timeout) > current){ return false; } return true; } public void setBaseDao(IBaseDao<User> baseDao) { this.baseDao = baseDao; } public void setSessionDao(IBaseDao<SimpleSessionEntity> sessionDao) { this.sessionDao = sessionDao; } }
    复制代码

    我快被自己蠢哭了,在继承EnterpriseCacheSessionDAO 只实现了readSession,妄想自己新建一个SimpleSession来返回给shiro使用,尝试过很多次之后不行,跟着调试了很多shiro源码,发现在SimpleSession中Shiro不仅设置了基本的属性,更重要的是设置了Attribute,但是我自己新建的SimpleSession没有,所以认证是失败的,所以在此敬告各位一定要记得实现save和update方法。

    虽然走了很多弯路,但是随着对shiro源码的调试学习,对shiro了解更深了,不再仅仅停留在只会使用的地步上,有深入。

     


     

     

    好了到此为止,正文完了,我们开头提出的问题都解决完了,记下来掰扯掰扯在做APP登录过程中遇到的问题以及一些自己的体会。

    关于系统安全

    在考虑APP登录的时候考虑了很多安全因素

    • 在用户使用用户名和密码登录的时候,对密码进行加密
    • 会话保持如果使用cookie这种技术的话,存在被别人截取cookie之后就可以认证登录了
    • 在本地保存密码肯定是不合适的,如果保存cookie(token)的话,手机被root之后,很容易就可以看得到了,比如Android的就只是一个xml文件,所以cookie保存要加密,加密之后提高了破解门槛,加密就涉及到秘钥的问题了,秘钥如果写在代码里面,java被反编译之后就很容易秘钥找得到了,当然了google早就已经开始支持NDK(即Android原生开发,这个原生是指使用C/C++开发,编译成为so文件,在java中调用),这样又加大了破解难度,使用Hybrid就更不用说了,直接解压安装包就可以看到了。
    • cookie如果保存在本地,更新的时机(频率)是什么,这样就算是cookie泄露了,也只是在某一段时间内有用(当然了,对于“有心人”来说“这段时间”已经足够做一些事儿了)

    在考虑这些问题的时候我意识到:

    • 安全只是相对的(攻与防本来就是一件你强我更强的事,有攻击,防御就会增强,防御增强了,攻击要想成功就得更强)
    • 安全不是在技术上越安全越好,要考虑实际应用场合、投入的成本(往往不是技术不能实现,而是要考虑实际情况,包括成本、信息的重要程度等等,这就是一种工程思维)

    展开全文
  • Kingbase数据库web统一管理平台

    千次阅读 2019-08-03 21:35:15
    1、安装Kingbase金仓数据库后,通过打开web管理平台,可以方便的进行远程维护。 示例地址:https://192.168.0.1:54328/webstudio 2、输入用户名密码登录。 3、包括:数据库服务器管理,交互式SQL工具,性能...

    1、安装Kingbase金仓数据库后,通过打开web管理平台,可以方便的进行远程维护。
       示例地址:https://192.168.0.1:54328/webstudio

    2、输入用户名密码登录。

    3、包括:数据库服务器管理,交互式SQL工具,性能监控与调优三大类,功能很丰富。

    4、输入标准SQL,在线查询维护数据,对于数据分析、统计都是很方便的。

    5、数据库管理中还包括许多功能,真的很丰富,国产数据库真的不比国外的差,并且更好用。

    6、Treesoft已实现Kingbase金仓数据库的适配,数据汇聚,数据抽取、数据融合,数据分析更方便了。

    展开全文
  • 登录请求表单数据 密钥与加密密码均为Base64编码 常见加密: 1)数据加密标准(DES Data Encryption Standard):DES(密钥长度64位)(ECB模式) 2)分组密码算法:AES(密钥长度在128位及以上)(GCM或...
  • 先说下背景,项目包含一个管理系统(web)和门户网站(web),还有一个手机APP(包括Android和IOS),三个系统共用一个后端,在后端使用shiro进行登录认证和权限...web和APP可以用shiro统一登录认证吗? 可以。假如
  • web开发中我们大量用到java端提供的WebApi,如果没有一个统一的返回结果格式是很痛苦的一件事情。 开始玩蛇以LEAP环境如何使用和配置RestService 文章中的例子为基础。定义枚举类ResultCodepackage ...
  • html css制作的web前端登录界面

    千次阅读 多人点赞 2020-08-02 23:15:28
    web前端登录界面
  • 统一登录门户系统

    千次阅读 2020-04-04 21:02:19
    常见的统一登录要求,还是基于一个统一的入口,由统一登录入口完成登录后,可以自由访问其他系统,而其他系统的用户登录应跳转到统一登录入口。 可能存在的问题: 1.用户系统如何建立,如何解决存量用户。 2.应...
  • WEB应用的后台门户都有登录入口。做过几次登录的功能。就第一次会感觉难。难再功能菜单的级联查询组装,网上查一查。自己debug试试,最后搞定了.然后就把代码小心保存,以后就copy copy copy。哈哈!今天对springboot...
  • asp.net web api 登录未授权

    千次阅读 2015-05-01 17:21:14
    使用统一的cookie限制访问asp.net web page和asp.net web api,不过当api未授权时,跳转到了登录页面,一堆的html代码不利于被调用端的呈现和识别,故: 1. 添加Attribute: AuthCheckFilter using ...
  • java web 通用返回json 统一返回结果

    千次阅读 2018-12-10 03:10:41
    开源个自己封装的通用json返回吧,自我感觉写的还行…emmm… ... * web专用返回 * @author Orange * @date 2018/10/28 */ public class Response&amp;lt;T&amp;gt; { private int code; ...
  • 前言:这学期有Java web的课,老师布置了一个小任务,实现web后台的登录验证和密码修改,以及加入过滤器来设置用户的权限,比如普通用户不能访问后台的管理页面,还用字符编码过滤器实现对页面字符编码的统一。...
  • 另外需要特别注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求,文档: ...
  • 公司子系统整合统一登录的架构

    千次阅读 2018-12-27 11:49:13
    如下图是公司的统一登录界面: 众多子系统的登录页面不再使用,所有登录走统一登录页面,登录时选择你要登录的系统,这里以我改造的安全管理系统为例。 在安全管理系统项目中加入一个整合的jar包,其实就是一个...
  • 绝对完全跨域统一单点登录登出

    万次阅读 热门讨论 2018-05-06 16:38:17
    如:淘宝与天猫,登出也如此,一个系统登出,其他系统的登录也随之失效,这就是统一单点登录登出。 这里配置三个web系统,一个用户中心系统为栗子 配置hosts实现跨域: 127.0.0.1 ssofront.ljtest.xxxx.com #...
  • 浅谈Web登录认证类漏洞

    千次阅读 2020-01-12 00:48:31
    做渗透测试也有一段时间了,每次对目标站点进行渗透的时候都发现登录方面的问题特别多,针对Web登录认证这块,我一直想要写个帖子进行全面点的总结,耐于目前处于实习阶段,工作也较多,所以推迟到了如今,话不多说...
  • CAS统一登录认证(1): 搭建 CAS Server

    千次阅读 2019-03-04 10:15:33
    搭建 CAS Server ...CAS(Central Authentication Service) 是Yale大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的单点登录解决方法(属于Web SSO)。 1.2SSO 简介 单点登录(S...
  • 在这篇文章中,我将围绕一个多应用环境下统一认证服务组件的架构展开讨论,探讨如何利用Web服务所带来的好处,实现跨平台跨应用的统一身份识别和权限认证。同时将其拓展到多种应用模式中去,包括Internet公用服务、...
  • AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容,它通过对既有程序定义一个切入点,然后在其...
  • Web 单点登录系统

    万次阅读 2010-02-28 22:17:00
    具体可参见 用CAS原理构建单点登录。互联网发展之后,多个网站需要统一认证,业界需要适合互联网的单点登陆技术。2002年,微软提出了passport服务,由微软统一提供帐号和认证服务,理所当然,大家都不愿意受制于微软...
  • 分布式系统统一登录模块设计

    千次阅读 2018-12-10 10:31:35
    维基百科对于单点登录的定义:  单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就...
  • 流程图

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,485
精华内容 36,594
关键字:

web统一登录