Shiro安全框架案例


基於Shiro的用戶認證(不包含授權)

Spring整合Shiro

shiro原理

1.1   搭建環境

1.1.1      web模塊 pom.xml

<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!--shiro核心包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency>

1.1.2  Web.xml配置

<!-- Shiro Security filter filter-name這個名字的值將來還會在spring中用到,本段代碼原樣粘貼,注意該過濾器是代理過濾器,它什么都不干,可以通過再Spring整合中配置相應的過濾器權限攔截器進行相應的過濾器攔截--> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param>
<!--如果設置"targetFilterLifecycle"為true,則spring來管理Filter.init()和Filter.destroy();若為false,則這兩個方法失效--> <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>

1.1.3  Spring整合shiro  applicationContext-shiro.xml

 <description>Shiro與Spring整合</description> <!--安全管理器--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 引用自定義的realm --> <property name="realm" ref="authRealm"/> </bean> <!-- 自定義Realm域的編寫 --> <bean id="authRealm" class="此處為自定義Realm域的全限定類名"> <!-- 注入自定義Realm域的密碼比較器 --> <property name="credentialsMatcher" ref="customerCredentialsMatcher" ></property> </bean> <!-- 密碼比較器:密碼加密和比較 --> <bean id="customerCredentialsMatcher" class="自定義的證書匹配器所在的全限定類名"/> <!-- filter-name這個名字的值來自於web.xml中filter的名字 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!--登錄頁面 --> <property name="loginUrl" value="/login.jsp"></property> <!-- 登錄失敗后 跳轉到未經授權的頁面 --> <property name="unauthorizedUrl" value="/unauthorized.jsp"></property>  <!--過濾器鏈定義,此處為訪問路徑設置過濾器鏈--> <property name="filterChainDefinitions"> <!-- /**代表下面的多級目錄也過濾,等號后面的單詞就是過濾器 --> <value>

<!--如果該路徑的用戶不包含“模塊管理”權限就禁止訪問--> <!-- /system/module/list.do = perms["模塊管理"] userLogin.do /userLogin* = anon mylogiin.jsp /mylogin* = anon --> /index.jsp* = anon /login.jsp* = anon /login* = anon /logout* = anon /css/** = anon /img/** = anon /plugins/** = anon /make/** = anon <!-- --> /** = authc /*.* = authc </value> </property> </bean> <!-- 保證實現了Shiro內部lifecycle函數的bean執行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 生成代理,通過代理進行控制 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"/> </bean> <!-- 安全管理器 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <aop:aspectj-autoproxy proxy-target-class="true"/>

2.1 自定義realm

/** * 自定義reamlm*/ public class AuthRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private ModuleService moduleService; /** * 授權管理:授權 */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } /** * 身份認證 * 用於驗證輸入的用戶名密碼給,登錄 */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1.獲取到用戶界面輸入的用戶名和密碼 UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken; //2.獲取用戶出入的用戶名和密碼  String username = upToken.getUsername(); String password = new String(upToken.getPassword()); //3.根據用戶名查詢用戶對象  User user = userService.findByUsername(username); if(user != null) { //第一個參數:安全數據(user對象) //第二個參數:密碼(數據庫密碼) //第三個參數:當前調用realm域的名稱(類名即可) SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName()); return info; } return null; //subject.login()方法的時候會拋出異常  } }
AuthorizingRealm抽象類中被重寫的方法來源

2.2 自定義密碼比較 

在spring與shiro的整合文件中已經將該類交給realm域中,所以直接重寫方法doCredentialsMatch即可

/** * 密碼比較器 */ public class CustomCredentialsMatcher extends SimpleCredentialsMatcher { /** * 用戶密碼比較 * 1.對用戶輸入的密碼進行加密 * 2.比較用戶輸入的密碼和數據庫密碼是否一致 * @param token 用戶界面輸入的郵箱和密碼 * @param info 安全數據:用戶對象user * * 111111 + 固定值(加鹽) = xxxxxx */ public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { //1.獲取用戶輸入的密碼 UsernamePasswordToken upToken = (UsernamePasswordToken) token; String loginPassword = new String(upToken.getPassword()); String email = upToken.getUsername(); //2.對登錄密碼進行加密 //加密:使用MD5加密 String md5Paasword = Encrypt.md5(loginPassword, email);//密碼,鹽 //info.getPrincipals();//獲取安全數據,用戶對象 //獲取數據庫密碼 String dbPassword = (String)info.getCredentials(); //true:登錄成功,false:拋出異常 return md5Paasword.equals(dbPassword); } }

 2.3 用戶登錄url映射

//用戶登錄 @RequestMapping("/login") public String login(String username,String password) { //1、通過shiro框架提供的SecurityUtils工具類獲取Subject Subject subject = SecurityUtils.getSubject(); //2、構造用戶名密碼的安全對象upToken UsernamePasswordToken upToken = new UsernamePasswordToken(username,password); //3、通過Subject的login()方法將安全對象交給shiro的安全管理器SecurityManager  subject.login(upToken); //4、通過shiro獲取用戶對象主體,保存到session User user = (User) subject.getPrincipal(); //獲取完全對象 session.setAttribute("user",user); //5、查詢菜單數據 List<Module> moduleList = moduleService.findModuleByUserid(user.getId()); session.setAttribute("modules",moduleList); return "home/main"; }

 shiro學習推薦閱讀》》》》》

 》》》shiro的權限管理的注解開發只需要一個注解代碼

 /** * RequiresPermissions: * value : 權限名稱(標識) * 如果具備此權限:進入方法 * 不具備此權限:拋出異常 */ @RequiresPermissions("模塊管理") @RequestMapping(value = "/list",name = "查詢所有") public String list(@RequestParam(defaultValue = "1")int page,@RequestParam(defaultValue = "3")int size){ PageInfo info = moduleService.findAll(page,size); request.setAttribute("page",info); return "system/module/module-list"; }

2.4   頁面標簽展示

通過shiro標簽控制頁面按鈕和菜單的顯示

2.4.1      引入標簽庫

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

2.4.2      控制顯示

<shiro:hasPermission name="刪除部門"> <button type="button" class="btn btn-default" title="刪除" onclick='deleteById()'><i class="fa fa-trash-o"></i> 刪除</button> </shiro:hasPermission>

2.4 用戶退出

//退出 @RequestMapping(value = "/logout",name="用戶登出") public String logout(){ SecurityUtils.getSubject().logout(); //登出 return "forward:login.jsp"; }

shiro自動管理session,此處會將session中的用戶信息清除。

shiro獲取當前用戶的用戶名

Subject subject = SecurityUtils.getSubject();
Object principal = subject.getPrincipal();

 

 

點擊查看SpringBoot整合Shiro


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM