Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、受權、密碼和會話管理。使用Shiro的易於理解的API,您能夠快速、輕鬆地得到任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序java
Authentication:有時稱爲「登陸」,這是證實用戶是他們所說的用戶的行爲。
Authorization:訪問控制的過程,即肯定「誰」有權訪問「什麼」。
Session Manager:管理特定於用戶的會話,即便在非web或EJB應用程序中也是如此。
Cryptography:使用密碼算法保持數據安全,同時仍然易於使用。git
三個核心組件:Subject, SecurityManager 和 Realmsgithub
Subject:即「當前操做用戶」。可是,在Shiro中,Subject這一律念並不單單指人,也能夠是第三方進程、後臺賬戶(Daemon Account)或其餘相似事物。它僅僅意味着「當前跟軟件交互的東西」。Subject表明了當前用戶的安全操做,SecurityManager則管理全部用戶的安全操做。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro經過SecurityManager來管理內部組件實例,並經過它來提供安全管理的各類服務。
Realm: Realm充當了Shiro與應用安全數據間的「橋樑」或者「鏈接器」。也就是說,當對用戶執行認證(登陸)和受權(訪問控制)驗證時,Shiro會從應用配置的Realm中查找用戶及其權限信息。web
簡單介紹流程,首先須要導入的依賴算法
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.0</version> </dependency>
若是thymeleaf須要整合shiro的話導入以下依賴spring
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
自定義realmapache
package com.hzy.config; import com.hzy.pojo.User; import com.hzy.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; // 自定義realm public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; // 認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("認證"); UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; User user = userService.queryUserByName(token.getUsername()); if (user == null) { return null; } Subject currentSubject = SecurityUtils.getSubject(); currentSubject.getSession().setAttribute("loginUser",user); // 密碼認證shiro作 return new SimpleAuthenticationInfo(user,user.getPassword(),""); } // 受權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("受權"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // info.addStringPermission("user:add"); // 拿到當前用戶的對象 Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); //拿到user對象 // 設置當前用戶的權限 info.addStringPermission(currentUser.getPerms()); return info; } }
ShiroConfig 安全
package com.hzy.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 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; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { //ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean (@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager ) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); // 設置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); // 添加shiro內置過濾器 /* * anno:無需認證就能夠訪問 * authc:必須認證才能訪問 * user:必須擁有記住我功能才能訪問 * perms:擁有某個資源的權限才能訪問 * role:擁有某個角色的權限才能訪問 * */ // 攔截 Map<String,String> filterMap = new LinkedHashMap<>(); // 受權 filterMap.put("/user/add","perms[user:add]"); filterMap.put("/user/update","perms[user:update]"); //filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); // 設置登陸請求 bean.setLoginUrl("/toLogin"); // 未受權頁面 bean.setUnauthorizedUrl("/noauth"); return bean; } //DefaultWebSecurityManager @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 關聯UserRealm securityManager.setRealm(userRealm); return securityManager; } //建立realm對象 @Bean public UserRealm userRealm() { return new UserRealm(); } // 整合ShiroDialect:用來整合shiro和thymeleaf @Bean public ShiroDialect getShiroDialect() { return new ShiroDialect(); } }
MyController 網絡
package com.hzy.controller; import org.apache.catalina.security.SecurityUtil; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class MyController { @RequestMapping({"/","/index"}) public String index(Model model) { model.addAttribute("msg","hello shiro"); return "index"; } @RequestMapping("/user/add") public String add() { return "user/add"; } @RequestMapping("/user/update") public String update() { return "user/update"; } @RequestMapping("/toLogin") public String toLogin(){ return "login"; } @RequestMapping("/login") public String login(String username,String password, Model model) { // 獲取當前用戶 Subject subject = SecurityUtils.getSubject(); // 封裝用戶的登陸數據 UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); return "index"; }catch (UnknownAccountException e) { model.addAttribute("msg", "用戶名不存在"); return "login"; }catch (IncorrectCredentialsException e) { model.addAttribute("msg", "密碼錯誤"); return "login"; } } @RequestMapping("/noauth") @ResponseBody public String unauthorized() { return "未受權沒法訪問此頁面"; } }
效果演示,不一樣的用戶會看見不一樣的界面app
首頁是一個登陸的連接
登陸不一樣的用戶會看到不一樣的界面