jeecms登录流程

shiro配置(jeecms/WebRoot/WEB-INF/config/shiro-context.xml)

1.在地址栏中输入http://*.*.*.*:****/admin/cms/login.do,由上图可看出进入CmsAuthenticationFilter过滤器中,

执行onPreHandle方法,跳转到登录界面(解释如下)

isAccessAllowed 只要当前用户已经过认证就直接返回true,未认证返回false

onAccessDenied方法具体实现内容

protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  

        if (isLoginRequest(request, response)) {  //判断是否是登录请求  

            if (isLoginSubmission(request, response)) { // 是否是http post请求  

                if (log.isTraceEnabled()) {  

                    log.trace("Login submission detected.  Attempting to execute login.");  

                }  

                return executeLogin(request, response);  

            } else {  //如果是get方法则会返回true,跳转到登陆页面

                if (log.isTraceEnabled()) {  

                    log.trace("Login page view.");  

                }  

                return true;  

            }  

        } else {   //如果访问的是非登录页面,则跳转到登录页面

            if (log.isTraceEnabled()) {  

                log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +  "Authentication url [" + getLoginUrl() + "]");  

            }  

         saveRequestAndRedirectToLogin(request, response);  

           return false;  

       }  

2.登录页面提交后(post请求),跳转到admin/cms/login.do,进入登录方法,由于此路径权限设置为authc,shiro对该路径进行过滤,authc权限由CmsAuthenticationFilter(extends FormAuthenticationFilter)进行过滤。

和上面执行顺序一样,进入onAccessDenied方法,因是登录请求并且是post请求,进而执行executeLogin(request, response)方法。

protected boolean executeLogin(ServletRequest request,ServletResponse response) throws Exception {

//创建用户的身份、凭证

AuthenticationToken token = createToken(request, response);

if (token == null) {

String msg = "create AuthenticationToken error";

throw new IllegalStateException(msg);

}

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse res = (HttpServletResponse) response;

//principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体

//可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。

String username = (String) token.getPrincipal();

boolean adminLogin=false;

if (req.getRequestURI().startsWith(req.getContextPath() + getAdminPrefix())){

adminLogin=true;

}

String failureUrl = req.getParameter(FAILURE_URL);

//验证码校验

if (isCaptchaRequired(username,req, res)) {

String captcha = request.getParameter(CAPTCHA_PARAM);

if (captcha != null) {

if (!imageCaptchaService.validateResponseForID(session.getSessionId(req, res), captcha)) {

return onLoginFailure(token,failureUrl,adminLogin,new CaptchaErrorException(), request, response);

}

} else {

return onLoginFailure(token,failureUrl,adminLogin,new CaptchaRequiredException(),request, response);

}

}

CmsUser user=userMng.findByUsername(username);

if(user!=null){

//用户禁用返回true 未查找到用户或者非禁用返回false

if(isDisabled(user)){

return onLoginFailure(token,failureUrl,adminLogin,new DisabledException(),request, response);

}

//用户激活了返回true 未查找到用户或者非禁用返回false

if(!isActive(user)){

return onLoginFailure(token,failureUrl,adminLogin,new InactiveException(),request, response);

}

}

try {

Subject subject = getSubject(request, response);

subject.login(token); //执行shiro的登录操作

return onLoginSuccess(token,adminLogin,subject, request, response);

} catch (AuthenticationException e) {

//e.printStackTrace();

return onLoginFailure(token,failureUrl,adminLogin, e, request, response);

}

}

调用subject的login方法,login方法实现大致流程是用token去realm中取AuthenticationInfo对象,AuthenticationInfo对象存放的是正确的登录账号和密码,并和token中数据进行匹配,然后根据匹配情况返回相应的结果。realm中方法需自己实现,大致流程:从token中取出用户登录填写的账号,去查找正确的登录信息,若是查找不到,返回null,如果查找到对应的登录账号和密码,则封装到AuthenticationInfo对象中,并返回该对象。

/**

* 登录认证

*/

protected AuthenticationInfo doGetAuthenticationInfo(

AuthenticationToken authcToken) throws AuthenticationException {

UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

CmsUser user = cmsUserMng.findByUsername(token.getUsername());

if (user != null) {

UnifiedUser unifiedUser = unifiedUserMng.findById(user.getId());

return new SimpleAuthenticationInfo(user.getUsername(), unifiedUser.getPassword(), getName());

} else {

return null;

}

}

 

/**

* 登录成功

*/

private boolean onLoginSuccess(AuthenticationToken token,boolean adminLogin,Subject subject,

ServletRequest request, ServletResponse response)

throws Exception {

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse res = (HttpServletResponse) response;

String username = (String) subject.getPrincipal();

CmsUser user = cmsUserMng.findByUsername(username);

String ip = RequestUtils.getIpAddr(req);

Date now = new Timestamp(System.currentTimeMillis());

String userSessionId=session.getSessionId((HttpServletRequest)request, (HttpServletResponse)response);

userMng.updateLoginInfo(user.getId(), ip,now,userSessionId);

//管理登录

if(adminLogin){

cmsLogMng.loginSuccess(req, user);

}

unifiedUserMng.updateLoginSuccess(user.getId(), ip);

loginCookie(username, req, res);

//调用父类FormAuthenticationFilter中的onLoginSuccess方法

return super.onLoginSuccess(token, subject, request, response);

}

   在FormAuthenticationFilter中登录成功具体实现

   protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,

                                     ServletRequest request, ServletResponse response) throws Exception {

        issueSuccessRedirect(request, response); //直接重定向到成功页面

        //we handled the success redirect directly, prevent the chain from continuing:

        return false; //不再执行过滤器链后面的操作

    }

/**

* 登录失败

*/

private boolean onLoginFailure(AuthenticationToken token,String failureUrl,boolean adminLogin,AuthenticationException e, ServletRequest request,

ServletResponse response) {

String username = (String) token.getPrincipal();

HttpServletRequest req = (HttpServletRequest) request;

//管理登录

if(adminLogin){

cmsLogMng.loginFailure(req,"username=" + username);

}

return onLoginFailure(failureUrl,token, e, request, response);

}

//登录失败具体实现

private boolean onLoginFailure(String failureUrl,AuthenticationToken token,

AuthenticationException e, ServletRequest request,

ServletResponse response) {

String className = e.getClass().getName();

request.setAttribute(getFailureKeyAttribute(), className);

//登录错误地址不为空,在跳转到登录错误地址

if(failureUrl!=null||StringUtils.isNotBlank(failureUrl)){

try {

request.getRequestDispatcher(failureUrl).forward(request, response);

} catch (Exception e1) {

//e1.printStackTrace();

}

}

//则继续执行过滤器链后面的操作

return true;

}

 

转载于:https://my.oschina.net/xiao666123/blog/1554229

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值