使用Shiro做权限认证(4)

4 篇文章 0 订阅

上节讲了web应用的过滤器,这节我们自己定义一个过滤器。

(1 ) 我们来定义一个Filter用于限制某些url只能某些特定IP地址进行访问,代码如下:

public class IpIntAuthorizationFilter extends AuthorizationFilter {  

    private static Logger logger = Logger.getLogger(IpIntAuthorizationFilter.class);  


    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {  
        logger.info("来访者的IP是:"+request.getRemoteAddr());
        //限制只有内网能访问
        if(!request.getRemoteAddr().startsWith("10.128.249")){
            throw new IOException("No permission");
        }
        return true;  
    } 
}

AuthorizationFilter是用于做身份认证用的filter,继承自AccessControlFilter,当访问不允许时会重定向到unauthorizedUrl上去

(2) 在容器中声明filter

<bean id="ipfilter" class="com.rada.framework.filter.IpIntAuthorizationFilter"></bean>

(3) 将ipfilter注册到过滤器链中去

<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="/403" />
        <property name="filters">    
            <map>    
               <entry key="ipfilter" value-ref="ipfilter"/>
            </map>    
        </property>  

        <property name="filterChainDefinitions">
            <value>
                /* = ipfilter,authcBasic
            </value>
        </property>
    </bean>

大功告成,原则上,任何操作request的请求都可以声明新的过滤器来实现。在此基础上我们可以实现很多功能。
如果我们想进行访问访问的控制就可以继承AccessControlFilter;如果我们要添加一些通用数据我们可以直接继承PathMatchingFilter。
比如以下的代码就大概演示了org.apache.shiro.web.filter.authc.FormAuthenticationFilter工作流程:

public class FormLoginFilter extends PathMatchingFilter {  
    private String loginUrl = "/login.jsp";  
    private String successUrl = "/";  
    @Override  
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  
        if(SecurityUtils.getSubject().isAuthenticated()) {  
            return true;//已经登录过  
        }  
        HttpServletRequest req = (HttpServletRequest) request;  
        HttpServletResponse resp = (HttpServletResponse) response;  
        if(isLoginRequest(req)) {  
            if("post".equalsIgnoreCase(req.getMethod())) {//form表单提交  
                boolean loginSuccess = login(req); //登录  
                if(loginSuccess) {  
                    return redirectToSuccessUrl(req, resp);  
                }  
            }  
            return true;//继续过滤器链  
        } else {//保存当前地址并重定向到登录界面  
            saveRequestAndRedirectToLogin(req, resp);  
            return false;  
        }  
    }  
    private boolean redirectToSuccessUrl(HttpServletRequest req, HttpServletResponse resp) throws IOException {  
        WebUtils.redirectToSavedRequest(req, resp, successUrl);  
        return false;  
    }  
    private void saveRequestAndRedirectToLogin(HttpServletRequest req, HttpServletResponse resp) throws IOException {  
        WebUtils.saveRequest(req);  
        WebUtils.issueRedirect(req, resp, loginUrl);  
    }  

    private boolean login(HttpServletRequest req) {  
        String username = req.getParameter("username");  
        String password = req.getParameter("password");  
        try {  
            SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password));  
        } catch (Exception e) {  
            req.setAttribute("shiroLoginFailure", e.getClass());  
            return false;  
        }  
        return true;  
    }  
    private boolean isLoginRequest(HttpServletRequest req) {  
        return pathsMatch(loginUrl, WebUtils.getPathWithinApplication(req));  
    }  
}   

onPreHandle主要流程:
1、首先判断是否已经登录过了,如果已经登录过了继续拦截器链即可;
2、如果没有登录,看看是否是登录请求,如果是get方法的登录页面请求,则继续拦截器链(到请求页面),否则如果是get方法的其他页面请求则保存当前请求并重定向到登录页面;
3、如果是post方法的登录页面表单提交请求,则收集用户名/密码登录即可,如果失败了保存错误消息到“shiroLoginFailure”并返回到登录页面;
4、如果登录成功了,且之前有保存的请求,则重定向到之前的这个请求,否则到默认的成功页面。
此示例来自开涛老师的博客
第八章 拦截器机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值