shiro-登录验证

来源:互联网 发布:mysql 2002错误 编辑:程序博客网 时间:2024/06/07 05:48
shiro实现登录验证,可以用它自身的方法来实现,也可以自定义方法来实现登录验证,了解了shiro的登录逻辑,实现自定义的验证逻辑就很简单
1、用shiro方法实现
shiro配置:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >        <property name="securityManager" ref="securityManager" />        <property name="loginUrl" value = "/login" />        <property name="successUrl" value = "/"  />        <property name="unauthorizedUrl" value = "/unauthorize"/><property name="filterChainDefinitions">            <value>                /static/**=anon                /login=authc                /logout=logout                /unauthorize=authc                /**=user,perms            </value>        </property></bean>
由于shiro默认注册了FormAuthenticationFilter,所以配置中可以不需要为此方法定义bean,但有个前提,登录页面中的登录账号和密码,记住我的name必须和FormAuthenticationFilter默认的名称一致,如下图

如果登录页面的name和FormAuthenticationFilter不一致,则需要自己为FormAuthenticationFilter进行配置
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">        <property name="usernameParam" value="name"/>        <property name="passwordParam" value="password1"/>        <property name="rememberMeParam" value="rememberMe1"/>        <property name="loginUrl" value="/login"/>        <property name="successUrl" value="/"/></bean><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >        <property name="securityManager" ref="securityManager" />        <property name="loginUrl" value = "/login" />        <property name="successUrl" value = "/"  />        <property name="unauthorizedUrl" value = "/unauthorize"/><property name="filters">            <map>                <entry key="authc" value-ref="formAuthenticationFilter"/>            </map>        </property><property name="filterChainDefinitions">            <value>                /static/**=anon                /login=authc                /logout=logout                /unauthorize=authc                /**=user,perms <            </value>        </property></bean>
登录页面提交后,跳转到 /login,进入登录方法,由于此路径权限设置为authc,shiro对该路径进行过滤,authc权限由FormAuthenticationFilter进行过滤。登录请求进入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 {                if (log.isTraceEnabled()) {                    log.trace("Login page view.");                }                //allow them to see the login page ;)                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;        }}
其中 executeLogin(request, response)方法的具体实现在继承的AuthenticatingFilter里
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {        AuthenticationToken token = createToken(request, response);         if (token == null) {            String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +"must be created in order to execute a login attempt.";            throw new IllegalStateException(msg);        }        try {            Subject subject = getSubject(request, response);            subject.login(token);            return onLoginSuccess(token, subject, request, response);        } catch (AuthenticationException e) {            return onLoginFailure(token, e, request, response);        }}

剖析:createToken(request, response); 具体实现在子类FormAuthenticationFilter中

protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {    String username = getUsername(request);    String password = getPassword(request);    return createToken(username, password, request, response);}

从上可以看出,具体的登录账号和密码从request中取出来,并创建了token对象,调用subject的login方法,login方法实现大致流程是用token去realm中取AuthenticationInfo对象,AuthenticationInfo对象存放的是正确的登录账号和密码,并和token中数据进行匹配,然后根据匹配情况返回相应的结果。realm中方法需自己实现,大致流程:从token中取出用户登录填写的账号,去查找正确的登录信息,若是查找不到,返回null,如果查找到对应的登录账号和密码,则封装到AuthenticationInfo对象中,并返回该对象。
java代码:
@RequestMapping(value = "/login")public String toLogin(HttpServletRequest request, Model model){        String exceptionClassName = (String)request.getAttribute("shiroLoginFailure");        String error = null;        if(UnknownAccountException.class.getName().equals(exceptionClassName)) {            error = "用户名/密码错误";        } else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {            error = "用户名/密码错误";        } else if(exceptionClassName != null) {            error = "其他错误:" + exceptionClassName;        }        model.addAttribute("error", error);        return "login";  // 跳转到登录页面}

2、自定义登录实现
最关键的是在shiro配置中,登录提交的url需设置为不过滤处理,如提交到/login,则/login=anon,
方法中可实现自己的登录验证逻辑。若是账号密码匹配工作仍要shiro来完成,则将用户填写的账号和密码封装到token对象中,调用subject的login方法。
代码示例:
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);       try {            subject.login(token);        } catch (UnknownAccountException ua){            returnInfo.setMessage("用户名错误");        } catch (IncorrectCredentialsException ic){            returnInfo.setMessage("密码错误");        }   }

附:
1)shiro默认注册的filters
public enum DefaultFilter {
    anon(AnonymousFilter.class),
    authc(FormAuthenticationFilter.class),
    authcBasic(BasicHttpAuthenticationFilter.class),
    logout(LogoutFilter.class),
    noSessionCreation(NoSessionCreationFilter.class),
    perms(PermissionsAuthorizationFilter.class),
    port(PortFilter.class),
    rest(HttpMethodPermissionFilter.class),
    roles(RolesAuthorizationFilter.class),
    ssl(SslFilter.class),
    user(UserFilter.class);
}
2)登录异常
UnknownAccountException(账号不存在)
IncorrectCredentialsException(密码错误)
DisabledAccountException(帐号被禁用)
LockedAccountException(帐号被锁定)
ExcessiveAttemptsException(登录失败次数过多)
ExpiredCredentialsException(凭证过期)等

0 0
原创粉丝点击