搭建好SSM項目
項目中引入相關依賴
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- 添加mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.1</version>
</dependency>
<!-- 添加junit用於實現單元測試 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 添加mybatis依賴 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 整合mybatis時需要添加如下兩個jar文件-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--整合log4j2,目的是便於我們根據日誌的輸出調試代碼
一般添加完依賴會在類路徑添加一個log4j2.xml文件
-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<!-- 整合jackson (在本項目中對請求的響應我們要採用json格式) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.3</version>
</dependency>
<!--添加JSTL標籤庫的支持 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 整合文件上傳功能 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- 整合shiro 安全框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
web.xml文件中註冊shiro過濾器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>tzms</display-name>
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- shiro配置過濾器 DelegatingFilterProxy通過代理模式將spring容器中的bean和filter關聯起來 -->
<filter>
<filter-name>delegatingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<!-- 設置spring容器filter的bean id,如果不設置則找與filter-name一致的bean -->
<init-param>
<param-name>targetBeanName</param-name>
<param-value>shiro</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>delegatingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
添加shiro的配置文件
注意shiro的配置可以添加在spring的配置文件中。但是爲了便於管理我們再單獨創建一個shiro的配置文件,裏面的Schema還是spring的。
同時web.xml文件中加載spring的位置也需要調整
spring-shiro.xml中的內容
<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 配置web.xml中過濾器對應的spring容器的bean -->
<bean id="shiro" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
<!-- 註冊SecurityManager -->
<property name="securityManager" ref="securityManager"></property>
<!-- 登錄時訪問的鏈接 -->
<property name="loginUrl" value="/loginUI"></property>
<!-- 用戶無權限時需要訪問的頁面 -->
<property name="unauthorizedUrl" value="/errorUI"></property>
<!-- 設置 過濾器鏈 -->
<property name="filterChainDefinitions">
<value>
/bootstrap/** = anon
/dist/** = anon
/images/** = anon
/jquery/** = anon
/tzms/** = anon
<!-- 所有請求匿名訪問 /** = anon -->
<!-- 點擊登錄 不需要認證 -->
/login = anon
<!-- 退出 此方法會清空shiro中session的數據 -->
/logout = logout
<!-- 所有的url都必須要認證通過後纔可以訪問 -->
/** = authc
</value>
</property>
</bean>
<!-- 配置安全管理器對象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroUserRealm"></property>
</bean>
<!-- 配置自定義Realm -->
<bean id="shiroUserRealm" class="com.tanzhou.tzms.common.service.impl.ShiroRealmsOne">
<!-- 配置憑證匹配器 -->
<property name="credentialsMatcher" ref="credentialsMatcher"></property>
</bean>
<!-- 定義憑證匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 匹配散列算法 -->
<property name="hashAlgorithmName" value="MD5"></property>
<!-- 匹配散列次數 -->
<property name="hashIterations" value="1"></property>
</bean>
</beans>
常見shiro過濾器
過濾器名稱 | 過濾器類 | 說明 |
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | 匿名過濾器 |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | 如果繼續操作,需要做對應的表單驗證否則不能通過 |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | 基本http驗證過濾,如果不通過,跳轉屋登錄頁面 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | 登錄退出過濾器 |
noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter | 沒有session創建過濾器 |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | 權限過濾器 |
port | org.apache.shiro.web.filter.authz.PortFilter |
端口過濾器,可以設置是否是指定端口如果不是跳轉到登錄頁面 |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter |
http方法過濾器,可以指定如post不能進行訪問等 |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter |
角色過濾器,判斷當前用戶是否指定角色 |
ssl | org.apache.shiro.web.filter.authz.SslFilter |
請求需要通過ssl,如果不是跳轉回登錄頁 |
user | org.apache.shiro.web.filter.authc.UserFilter | 如果訪問一個已知用戶,比如記住我功能,走這個過濾器 |
創建Realm接口和實現類
完成realm的認證功能
SysShiroServiceImpl類內容
public class SysShiroServiceImpl implements SysShiroService {
@Override
public void login(String username, String password) {
Subject subject = SecurityUtils.getSubject();
if(subject.isAuthenticated())return;
// 把用戶名和密碼封裝爲 UsernamePasswordToken 對象
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try{//登錄認證 - 調用userRealm
subject.login(token);
}catch (IncorrectCredentialsException ice) {
throw new ServiceException("密碼錯誤!");
} catch(AuthenticationException ae){
ae.printStackTrace();
throw new ServiceException("認證失敗");
}
}
}
自定義Realm認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username =(String)token.getPrincipal();
//通過用戶名從數據庫中查詢到數據返回對象
SysUser userInfo = userDao.findObjectByName(username);
//從對象中得到加密後的密碼
String password = userInfo.getPassword();
//從對象中獲取到鹽值
String salt = userInfo.getSalt();
//將鹽值專爲十六進制
ByteSource saltSource = ByteSource.Util.bytes(salt);
//通過用戶ID從數據庫中查詢到首頁左側導航欄要顯示的菜單
List<Map<String, Object>> map = sysService.findUserMenus(userInfo.getId());
//創建CurrentUser類 將查詢得到的用戶id、用戶名稱和用戶需要顯示的菜單放到創建好的對象中
CurrentUser user = new CurrentUser();
user.setUserid(userInfo.getId());
user.setUsername(userInfo.getUsername());
user.setMenus(map);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,password,saltSource,this.getName());
return info;
}
完成controller
@RequestMapping("/login")
@ResponseBody
public JsonResult login(HttpSession session,String username,String password){
System.out.println(username+"/"+password);
loginService.login(username, password);
Subject subject = SecurityUtils.getSubject();
System.out.println("是否認證成功:"+subject.isAuthenticated());
return new JsonResult();
}
結果爲
密碼錯誤
密碼正確
執行原理流程