shiro web 集成案例详解

Shiro提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前端控制器,其是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。

本文涉及的源代码下载链接:http://pan.baidu.com/s/1qYjREsk 密码:negu

创建 Maven web工程

由于是web 工程,因此需要tomcat 或 jetty 作为容器。此处我们使用了jetty-maven-plugin和tomcat7-maven-plugin插件;这样可以直接使用“mvn jetty:run”或“mvn tomcat7:run”直接运行webapp了。然后通过URL http://localhost:8080/shiro/访问即可。有不会maven 的可以先学习 maven 教程。

另外我们还需要 servlet 和 shiro-web 的依赖,添加pom配置。

<dependency>  
    <groupId>javax.servlet</groupId>  
    <artifactId>javax.servlet-api</artifactId>  
    <version>3.0.1</version>  
    <scope>provided</scope>  
</dependency> 
<dependency>  
    <groupId>org.apache.shiro</groupId>  
    <artifactId>shiro-web</artifactId>  
    <version>1.2.2</version>  
</dependency> 

其他依赖请参考源码的pom.xml。限于篇幅我这里就不一一列举了。

web.xml 配置shiro

<filter>  
    <filter-name>iniShiroFilter</filter-name>  
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>  
    <init-param>  
        <param-name>configPath</param-name>  
        <param-value>classpath:shiro.ini</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>iniShiroFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping> 
  1. 使用IniShiroFilter作为Shiro安全控制的入口点,通过url-pattern指定需要安全的URL;
  2. 通过configPath指定ini配置文件位置,默认是先从/WEB-INF/shiro.ini加载,如果没有就默认加载classpath:shiro.ini,即默认相对于web应用上下文根路径;
  3. 也可以通过如下方式直接内嵌ini配置文件内容到web.xml
<init-param>  
    <param-name>config</param-name>  
    <param-value>  
        ini配置文件贴在这  
    </param-value>  
</init-param>  

源代码中列举了两个版本的shiro配置,这里只举例了一种,另外一种略过。

Shiro 与Spring集成

<filter>  
    <filter-name>shiroFilter</filter-name>  
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
    <init-param>  
        <param-name>targetFilterLifecycle</param-name>  
        <param-value>true</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>shiroFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

DelegatingFilterProxy作用是自动到spring容器查找名字为shiroFilter(filter-name)的bean并把所有Filter的操作委托给它。然后将ShiroFilter配置到spring容器即可:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
<property name="securityManager" ref="securityManager"/>  
<!—忽略其他,详见与Spring集成部分 -->  
</bean> 

Shiro 的[urls] 配置

[urls]部分的配置,其格式是: “url=拦截器[参数],拦截器[参数]”;即如果当前请求的url匹配[urls]部分的某个url模式,将会执行其配置的拦截器。比如anon拦截器表示匿名访问(即不需要登录即可访问);authc拦截器表示需要身份认证通过后才能访问;roles[admin]拦截器表示需要有admin角色授权才能访问;而perms[“user:create”]拦截器表示需要有“user:create”权限才能访问。shiro.ini配置部分见案例源码。

url模式使用Ant风格模式

Ant路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符“/”:
?:匹配一个字符,如”/admin?”将匹配/admin1,但不匹配/admin或/admin2;
*:匹配零个或多个字符串,如/admin*将匹配/admin、/admin123,但不匹配/admin/1;
**:匹配路径中的零个或多个路径,如/admin/**将匹配/admin/a或/admin/a/b。

url模式匹配顺序是按照在配置中的声明顺序匹配,即从头开始使用第一个匹配的url模式对应的拦截器链。如:

/bb/**=filter1  
/bb/aa=filter2  
/**=filter3  

如果请求的url是“/bb/aa”,因为按照声明顺序进行匹配,那么将使用filter1进行拦截。

登录 Servlet 实现

@WebServlet(name = "loginServlet", urlPatterns = "/login")  
public class LoginServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
      throws ServletException, IOException {  
        req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp);  
    }  
    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
      throws ServletException, IOException {  
        String error = null;  
        String username = req.getParameter("username");  
        String password = req.getParameter("password");  
        Subject subject = SecurityUtils.getSubject();  
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);  
        try {  
            subject.login(token);  
        } catch (UnknownAccountException e) {  
            error = "用户名/密码错误";  
        } catch (IncorrectCredentialsException e) {  
            error = "用户名/密码错误";  
        } catch (AuthenticationException e) {  
            //其他错误,比如锁定,如果想单独处理请单独catch处理  
            error = "其他错误:" + e.getMessage();  
        }  
        if(error != null) {//出错了,返回登录页面  
            req.setAttribute("error", error);  
            req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp);  
        } else {//登录成功  
            req.getRequestDispatcher("/WEB-INF/jsp/loginSuccess.jsp").forward(req, resp);  
        }  
    }  
}

doPost时进行登录,登录时收集username/password参数,然后提交给Subject进行登录。如果有错误再返回到登录页面;否则跳转到登录成功页面(此处应该返回到访问登录页面之前的那个页面,或者没有上一个页面时访问主页)。

基于Basic的拦截器身份验证

shiro-basicfilterlogin.ini配置如下:

[main]
authcBasic.applicationName=please login

perms.unauthorizedUrl=/unauthorized
roles.unauthorizedUrl=/unauthorized
[users]
xttblog=123,admin
codedq=123

[roles]
admin=user:*,menu:*

[urls]
/role=authcBasic,roles[admin]

authcBasic是org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter类型的实例,其用于实现基于Basic的身份验证;applicationName用于弹出的登录框显示信息使用,如下图所示:

Shiro Basic 认证

[urls]部分配置了/role地址需要走authcBasic拦截器,即如果访问/role时还没有通过身份验证那么将弹出如上图的对话框进行登录,登录成功即可访问。另外需要把shiroConfigLocations改为shiro-basicfilterlogin.ini。

基于表单的拦截器身份验证

shiro-formfilterlogin.ini配置如下:

[main]
authc.loginUrl=/formfilterlogin
authc.usernameParam=username
authc.passwordParam=password
authc.successUrl=/
authc.failureKeyAttribute=shiroLoginFailure

perms.unauthorizedUrl=/unauthorized
roles.unauthorizedUrl=/unauthorized

[users]
xttblog=123,admin
codedq=123

[roles]
admin=user:*,menu:*

[urls]
/static/**=anon
/formfilterlogin=authc
/role=authc,roles[admin]
/permission=authc,perms["user:create"]

authc是org.apache.shiro.web.filter.authc.FormAuthenticationFilter类型的实例,其用于实现基于表单的身份验证;通过loginUrl指定当身份验证时的登录表单;usernameParam指定登录表单提交的用户名参数名;passwordParam指定登录表单提交的密码参数名;successUrl指定登录成功后重定向的默认地址(默认是“/”)(如果有上一个地址会自动重定向带该地址);failureKeyAttribute指定登录失败时的request属性key(默认shiroLoginFailure);这样可以在登录表单得到该错误key显示相应的错误消息;

同意的需要在web.xml中把shiroConfigLocations改为shiro- formfilterlogin.ini。

其他授权(角色/权限验证)、退出等见项目源码。本文涉及的源代码下载链接:http://pan.baidu.com/s/1qYjREsk 密码:negu

shiro web 集成案例详解

: » shiro web 集成案例详解

原创文章,作者:306829225,如若转载,请注明出处:https://blog.ytso.com/251550.html

(0)
上一篇 2022年5月3日
下一篇 2022年5月3日

相关推荐

发表回复

登录后才能评论