在之前的介紹中,我們用的是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