Subject :使用者主體(把操作交給SecurityManager)
SecurityManager:安全管理器(關聯Realm)
Realm :shiro連線資料的橋樑
shiro依賴
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
thymeleaf整合shiro許可權標籤
<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
整合Mybatis
dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
建立UserController.java
@RequestMapping("/login")
public String login(String name,String password,boolean rememberMe, Model model) {
//1、獲取subject
Subject subject = SecurityUtils.getSubject();
//2、封裝使用者資料
UsernamePasswordToken token = new UsernamePasswordToken(name,password,rememberMe);
//3、執行登入方法
try {
//交給Realm處理--->執行它的認證方法
subject.login(token);
//登入成功
return "redirect:/testThymeleaf";
}catch (UnknownAccountException e){
//登入失敗:使用者名稱不存在
model.addAttribute("msg","使用者名稱不存在");
return "user/login";
}catch (IncorrectCredentialsException e){
//登入失敗:密碼錯誤
model.addAttribute("msg","密碼錯誤");
return "user/login";
}
}
建立UserRealm.java
package com.brewin.shiro.config;
import org.apache.shiro.SecurityUtils;
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.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;
import com.brewin.shiro.domain.User;
import com.brewin.shiro.service.UserService;
public class UserRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
//授權邏輯
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
System.out.println("執行授權邏輯");
//給資源進行授權
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//新增資源的授權字串
// info.addStringPermission("user:update");
//獲取當前登入使用者
Subject subject = SecurityUtils.getSubject();
User user = (User)subject.getPrincipal();
//System.out.println(subject.getPrincipal());
User dbUser = userService.findById(user.getId());
// info.addStringPermission("user:add");
info.addStringPermission(dbUser.getPerms());
return info;
}
//認證邏輯
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("執行認證邏輯");
//編寫shiro判斷邏輯,判斷使用者名稱和密碼
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
User user = userService.findByName(token.getUsername());
//1、判斷使用者名稱
if(user == null){
//使用者名稱不存在
return null; //shiro底層會丟擲UnKnowAccountException
}
//2、判斷密碼, 這裡的user是principal
return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
}
}
分為認證與授權
建立ShiroConfig.java
@Configuration
public class ShiroConfig {
//建立ShiroFileterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//設定安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//新增shiro內建過濾器
/**
* anno:無需認證(登入)可以訪問
* authc:必須認證才可以訪問
* user:如果使用rememberMe的功能可以直接訪問
* perms:該資源必須得到資源許可權才可以訪問
* role:該資源必須得到角色許可權才可以訪問
*/
Map<String,String> filterMap = new LinkedHashMap<String,String>();
//配置記住我或認證透過可以訪問的地址
filterMap.put("/testThymeleaf", "user");
//設定放行頁面
filterMap.put("/testThymeleaf","anon");
filterMap.put("/login","anon");
//授權過濾器
filterMap.put("/add","perms[user:add]");
filterMap.put("/update","perms[user:update]");
filterMap.put("/*", "authc");
//攔截後預設跳轉到login.jsp,修改跳轉頁面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//設定未授權提示頁面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
//建立DefaultWebSecurityManager
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm) {
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//關聯Realm
securityManager.setRealm(userRealm);
return securityManager;
}
//建立Realm
@Bean(name="userRealm")
public UserRealm getRealm() {
return new UserRealm();
}
/**
* 配置ShiroDialect,用於thymeleaf和shiro標籤配合使用
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
/**
2 * cookie物件;
3 * rememberMeCookie()方法是設定Cookie的生成模版,比如cookie的name,cookie的有效時間等等。
4 * @return
5 */
@Bean
public SimpleCookie rememberMeCookie(){
//System.out.println("ShiroConfiguration.rememberMeCookie()");
//這個引數是cookie的名稱,對應前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//<!-- 記住我cookie生效時間30天 ,單位秒;-->
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
/**
* cookie管理物件;
* rememberMeManager()方法是生成rememberMe管理器,而且要將這個rememberMe管理器設定到securityManager中
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager(){
//System.out.println("ShiroConfiguration.rememberMeManager()");
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的金鑰 建議每個專案都不一樣 預設AES演算法 金鑰長度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
return cookieRememberMeManager;
}
}
ShiroDialect與thymeleaf標籤配合使用,可僅顯示授權頁面
建立test.html頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${title}"></h1>
<div shiro:hasPermission="user:add">
進入使用者新增功能:<a th:href="@{/add}">使用者新增</a><br>
</div>
<div shiro:hasPermission="user:update">
進入使用者更新功能:<a th:href="@{/update}">使用者更新</a>
</div>
<a href="/toLogin">登入</a>
</body>
</html>
本作品採用《CC 協議》,轉載必須註明作者和本文連結