1.1. 分析Shiro的核心API
Subject: 用戶主體(把操作交給SecurityManager)
SecurityManager:安全管理器(關聯Realm)
Realm:Shiro連接數據的橋梁
1.2. Spring Boot整合Shiro
1.2.1. 導入shiro與spring整合依賴
修改pom.xml
<!-- shiro與spring整合依賴 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency>
1.2.2. 自定義Realm類
package com.itheima.shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;/*** 自定義Realm * @author lenovo * */public class UserRealm extends AuthorizingRealm{/** * 執行授權邏輯 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {System.out.println("執行授權邏輯");return null;}/** * 執行認證邏輯 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("執行認證邏輯");return null;}}
1.2.3. 編寫Shiro配置類(*)
package com.itheima.shiro;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** Shiro的配置類 * @author lenovo * */@Configurationpublic class ShiroConfig {/** * 創建ShiroFilterFactoryBean */ @Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//設置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);return shiroFilterFactoryBean;}/** * 創建DefaultWebSecurityManager */@Bean(name="securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯realmsecurityManager.setRealm(userRealm);return securityManager;}/** * 創建Realm */@Bean(name="userRealm")public UserRealm getRealm(){return new UserRealm();}}
1.3. 使用Shiro內置過濾器實現頁面攔截
package com.itheima.shiro;import java.util.LinkedHashMap;import java.util.Map;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** Shiro的配置類 * @author lenovo * */@Configurationpublic class ShiroConfig {/** * 創建ShiroFilterFactoryBean */@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//設置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);//添加Shiro內置過濾器/** * Shiro內置過濾器,可以實現權限相關的攔截器 * 常用的過濾器: * anon: 無需認證(登錄)可以訪問 * authc: 必須認證才可以訪問 * user: 如果使用rememberMe的功能可以直接訪問 * perms: 該資源必須得到資源權限才可以訪問 * role: 該資源必須得到角色權限才可以訪問 */Map<String,String> filterMap = new LinkedHashMap<String,String>();/*filterMap.put("/add", "authc");filterMap.put("/update", "authc");*/filterMap.put("/testThymeleaf", "anon");filterMap.put("/*", "authc");//修改調整的登錄頁面shiroFilterFactoryBean.setLoginUrl("/toLogin");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}/** * 創建DefaultWebSecurityManager */@Bean(name="securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯realmsecurityManager.setRealm(userRealm);return securityManager;}/** * 創建Realm */@Bean(name="userRealm")public UserRealm getRealm(){return new UserRealm();}}
1.4. 實現用戶認證(登錄)操作
1.4.1. 設計登錄頁面
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>登錄頁面</title></head><body><h3>登錄</h3><form method="post" action="login">用戶名:<input type="text" name="name"/><br/>密碼:<input type="password" name="password"/><br/><input type="submit" value="登錄"/></form></body></html>
1.4.2. 編寫Controller的登錄邏輯
/*** 登錄邏輯處理 */@RequestMapping("/login")public String login(String name,String password,Model model){/** * 使用Shiro編寫認證操作 *///1.獲取SubjectSubject subject = SecurityUtils.getSubject();//2.封裝用戶數據UsernamePasswordToken token = new UsernamePasswordToken(name,password);//3.執行登錄方法try {subject.login(token);//登錄成功//跳轉到test.htmlreturn "redirect:/testThymeleaf";} catch (UnknownAccountException e) {//e.printStackTrace();//登錄失敗:用戶名不存在model.addAttribute("msg", "用戶名不存在");return "login";}catch (IncorrectCredentialsException e) {//e.printStackTrace();//登錄失敗:密碼錯誤model.addAttribute("msg", "密碼錯誤");return "login";}}
1.4.3. 編寫Realm的判斷邏輯
package com.itheima.shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;/*** 自定義Realm * @author lenovo * */public class UserRealm extends AuthorizingRealm{/** * 執行授權邏輯 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {System.out.println("執行授權邏輯");return null;}/** * 執行認證邏輯 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("執行認證邏輯");//假設資料庫的用戶名和密碼String name = "eric";String password = "123456";//編寫shiro判斷邏輯,判斷用戶名和密碼//1.判斷用戶名UsernamePasswordToken token = (UsernamePasswordToken)arg0;if(!token.getUsername().equals(name)){//用戶名不存在return null;//shiro底層會拋出UnKnowAccountException}//2.判斷密碼return new SimpleAuthenticationInfo("",password,"");}}
1.5. 整合MyBatis實現登錄
1.5.1. 導入mybatis相關的依賴
<!-- 導入mybatis相關的依賴 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.9</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- SpringBoot的Mybatis啟動器 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency>
1.5.2. 配置application.properties
位置:src/main/resources目錄下
spring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=rootspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcemybatis.type-aliases-package=com.itheima.domain
1.5.3. 編寫User實體
package com.itheima.domain;public class User {private Integer id;private String name;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}
1.5.4. 編寫UserMapper接口
package com.itheima.mapper;import com.itheima.domain.User;public interface UserMapper {public User findByName(String name);}
1.5.5. 編寫UserMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 該文件存放CRUD的sql語句 --><mapper namespace="com.itheima.mapper.UserMapper"><select id="findByName" parameterType="string" resultType="user">SELECT id,NAME,PASSWORDFROMuser where name = #{value}</select></mapper>
1.5.6. 編寫業務接口和實現
接口:
package com.itheima.service;import com.itheima.domain.User;public interface UserService {public User findByName(String name);}
實現;
package com.itheima.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.itheima.domain.User;import com.itheima.mapper.UserMapper;import com.itheima.service.UserService;@Servicepublic class UserServiceImpl implements UserService{//注入Mapper接口@Autowiredprivate UserMapper userMapper;@Overridepublic User findByName(String name) {return userMapper.findByName(name);}}
1.5.7. 添加@MapperScan註解
package com.itheima;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/*** SpringBoot啟動類 * @author lenovo * */@SpringBootApplication@MapperScan("com.itheima.mapper")public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
1.5.8. 修改UserRealm
package com.itheima.shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;import com.itheima.domain.User;import com.itheima.service.UserService;/*** 自定義Realm * @author lenovo * */public class UserRealm extends AuthorizingRealm{/** * 執行授權邏輯 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {System.out.println("執行授權邏輯");return null;}@Autowiredprivate UserService userSerivce;/** * 執行認證邏輯 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {System.out.println("執行認證邏輯");//編寫shiro判斷邏輯,判斷用戶名和密碼//1.判斷用戶名UsernamePasswordToken token = (UsernamePasswordToken)arg0;User user = userSerivce.findByName(token.getUsername());if(user==null){//用戶名不存在return null;//shiro底層會拋出UnKnowAccountException}//2.判斷密碼return new SimpleAuthenticationInfo("",user.getPassword(),"");}}