Shiro处理简单的身份验证的分析及实例

在两天在看Shiro,开涛兄的教程还是写的比较易读,差不多看了一天吧,就准备拿来用了。
可能是想的太简单了,在用的时候确实碰到一些问题,就拿最简单的身份验证来说吧:
需要说明的是,这里是集成在Spring中使用,身份验证我直接使用了Shiro提供的

org.apache.shiro.web.filter.authc.FormAuthenticationFilter

如果url应用了该拦截器,那么处理流程是大致这样的:
这里写图片描述
由于之前用markdown花的流程图显示不下,所以还是改成图片形式了。

比如我们要用FormAuthenticationFilter来做一个简单的身份验证的话,也是很简单的:

  1. 首先我们分别写好处理登陆的get请求和post请求
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String showLoginPage() {
        return "user/login";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String submitLoginForm(User user, HttpServletRequest request,
            Model model) {

        String errorClassName = (String) request
                .getAttribute("shiroLoginFailure");

        String authticationError = null;
        if (UnknownAccountException.class.getName().equals(errorClassName)) {
            authticationError = "用户名/密码错误";
        } else if (IncorrectCredentialsException.class.getName().equals(
                errorClassName)) {
            authticationError = "用户名/密码错误";
        } else if (errorClassName != null) {
            authticationError = "未知错误:" + errorClassName;
        }
        model.addAttribute("authticationError", authticationError);

        return showLoginPage();
    }

在post请求中我们需要根据request中的错误信息来翻译出需要显示的消息内容。若需要国际化的话,也可以用ResourceBundle来做。
需要注意的是,只有当登陆报错了才会进来这个方法中来。若身份验证成功的话,会直接跳转到之前的访问地址或是successfulUrl去。好了,接下来看看配置文件:

    <!-- 凭证匹配器 这里简单写了一个无需加密的匹配 -->
    <bean id="credentialsMatcher" class="com.zhu.prototype.shiro.credential.PlainPasswordMatcher">
    </bean>

    <bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"></property>
        <property name="authenticationQuery" value="select password from user where username = ?"></property>
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 安全管理器 DefaultWebSecurityManager默认使用ServletContainerSessionManager来管理session-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realms">
            <list>
                <ref bean="jdbcRealm" />
            </list>
        </property>
    </bean>

    <!-- 基于Form表单的身份验证过滤器 -->
    <bean id="formAuthenticationFilter"
        class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
        <property name="usernameParam" value="username" />
        <property name="passwordParam" value="password" />
        <property name="loginUrl" value="/login" />
        <property name="successUrl" value="/news/newsList"></property>
    </bean>

登陆成功后,会在session中默认设置几个属性:

{org.apache.shiro.subject.support.DefaultSubjectContext_AUTHENTICATED_SESSION_KEY=true,
org.apache.shiro.web.session.HttpServletSession.HOST_SESSION_KEY=0:0:0:0:0:0:0:1,
org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY=zhu}

如果我们需要注册attribute的话,我的想法是继承FormAuthenticationFilter(不知道Shiro是否有提供别的配置来完成?),然后重写onLoginSuccess(…),原定义如下:

    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;
    }

可改写为

    @Override
    protected boolean onLoginSuccess(AuthenticationToken token,
            Subject subject, ServletRequest request, ServletResponse response)
            throws Exception {

        super.onLoginSuccess(token, subject, request, response);
        initCustomSessionAttributes(((HttpServletRequest) request)
                .getSession(false), token);

        return false;
    }

    protected void initCustomSessionAttributes(HttpSession session,
            AuthenticationToken token) {

        String username = token.getPrincipal().toString();
        User user = userService.getUserByUsername(username);
        UserPreferences preferences = new UserPreferences();
        preferences.setUsername(user.getUsername());
        session.setAttribute("userPreferences", preferences);
    }

最后给出Shiro中常见的验证不通过报的错误:

  • DisabledAccountException (禁用的帐号)
  • LockedAccountException (锁定的帐号)
  • UnknownAccountException(错误的帐号)
  • ExcessiveAttemptsException(登录失败次数过多)
  • IncorrectCredentialsException (错误的凭证)
  • ExpiredCredentialsException (过期的凭证)
  • ……
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值