在之前的介绍中,我们用的是j2se环境,现在如果集成 web,该怎么配置呢?在web环境下,怎么对url进行身份认证,角色认证以及权限认证呢?
官方文档:shiro-web
首先来搭建一下环境。采用原始的jsp开发环境,集成框架的话,后面的章节介绍。
需要引入的依赖;jsp,servlet,common-logging,shiro-core,shiro-web
第一步:配置web.xml 加入shiro拦截器
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
把所有用户请求拦截,交给ShiroFilter处理。在里面有一个默认操作,读取WEB-INF下的shiro.ini配置文件。
第二步:在WEB-INF目录下,写shiro.ini配置文件
我们先不适用jdbc Realm.采用简单的Text Realm:
[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=unpermitted.jsp
[users]
java=1234,admin
12=12,teacher
jack=1234
[roles]
admin=user:*
teacher=student:*
[urls]
/login=anon
/admin=authc
/student=roles[teacher]
/delete=perms["user:delete"]
在这里面我们定义了3个用户,分别是java,12,jack并且赋予他们各自角色,同时赋予各角色权限。
在[urls]下面配置请求拦截类型:
拦截类型:
anon:不进行拦截,游客身份(不需要登录的)
authc:拦截并进行身份验证,简单说就是必须登录后才能访问,在上面的[main]也定义了该验证,如果不通过后,要重新请求登录的login请求
roles:拦截进行角色认证,但首先要进行身份认证,认证通过后,在进行角色认证。角色认证不通过,在上面的[main]也进行了roles的配置,将认证不通过的unauthorizedUrl设置为:unauthorized.jsp(角色认证不通过)
perms:拦截请求进行权限认证,也是先进行身份认证,身份认证通过后,再进行权限认证,如果权限认证不通过,在上面的[main]也进行了配置,将认证不通过的url设置为;unpermitted.jsp(权限认证不通过)
第三步:写测试所需的Servlet以及jsp页面。
在web.xml中配置这两个servlet:
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.java.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>adminServlet</servlet-name>
<servlet-class>com.java.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>adminServlet</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
在LoginServlet中进行身份认证:
public class LoginServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login doget");
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("login dopost");
String userName = req.getParameter("userName");
String password = req.getParameter("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
try {
subject.login(token);
resp.sendRedirect("success.jsp");
}catch(Exception e) {
e.printStackTrace();
req.setAttribute("errorMsg", "用户名或密码错误");
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
}
当从login页面传过来的参数,放到token中,进行当前用户的登录,如果登录成功,shiro将自动将当前用户信息存到session.
并重定向到success.jsp 认证不通过,获取异常并将错误信息带回login.jsp
login里面就一句OK,
unauthoied.jsp:“角色认证未通过”
unpermitted.jsp:"用户权限不足"
第四步,测试
身份认证测试:
在未登录前,请求admin请求:
会被拦截并送到login.jsp
角色认证测试:
测试student请求,该请求只有拥有teacher角色的用户才能请求:
用java用户登录后,再请求student
权限认证测试:
测试delete请求,该请求只有拥有user:delete权限的用户才能访问:
用jack用户登录后,请求delete请求:
补充一个知识点:
Url 匹配方式 ? 匹配一个字符 /admin? 可以匹配/admin1/admin2 但是不能匹配/admin12/admin * 匹配零个或者一个或者多个字符 /admin* 可以匹配 /admin/admin1/admin12 但是不能匹配/admin/abc ** 匹配零个或者多个路径 /admin/** 可以匹配/admin/admin/a /admin/a/b