Shiro+SpringBoot認證
阿新 • • 發佈:2020-08-12
該部落格以Web為基礎
一、引入依賴
shiro-all包含shiro所有的包、shiro-core是核心包、shiro-web是與web整合、shiro-spring是與spring整合、shiro-ehcache是與EHCache整合、shiro-quartz是與任務排程quartz整合等等。這裡我們只需要引入shiro-spring即可。
1 <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
2 <dependency>
3 <groupId>org.apache.shiro</groupId>
4 <artifactId>shiro-spring</artifactId>
5 <version>1.5.3</version>
6 </dependency>
二、Controller層
@RestController @RequestMapping("/account") public class AccountController {
/**
* 登入
* @param username
* @param password
* @return
*/
@PostMapping(path = "/login")
public ResultMsg login(
@RequestParam(value = "aaccount")String username,
@RequestParam(value = "apassword")String pwd,@RequestParam("check") Integer check ) {
ResultMsg resultMsg = new ResultMsg();
// 獲取當前使用者
Subject subject = SecurityUtils.getSubject();
/**
* 判斷當前使用者是否已經認證過
*/
// System.out.println("是否記住我==="+subject.isRemembered());
if (!subject.isAuthenticated()) {// 封裝使用者的登入資料
UsernamePasswordToken token = new UsernamePasswordToken(username,pwd);
Boolean rememberMe = check == 1 ? true:false;
System.out.println(rememberMe);
token.setRememberMe(rememberMe); //記住我
try {
subject.login(token); //登入認證
resultMsg.setState(200);
resultMsg.setMsg("登入成功");
return resultMsg;
} catch (UnknownAccountException u) {
System.err.println("使用者不存在");
resultMsg.setState(412);
resultMsg.setMsg("使用者不存在");
return resultMsg;
} catch (IncorrectCredentialsException i) {
System.err.println("密碼錯誤");
resultMsg.setState(412);
resultMsg.setMsg("密碼錯誤");
return resultMsg;
} catch (LockedAccountException l) {
System.err.println("賬戶鎖定");
resultMsg.setState(412);
resultMsg.setMsg("賬戶鎖定");
return resultMsg;
}
} else {
resultMsg.setState(403);
resultMsg.setMsg("此賬戶已在其他地方登入,是否強制下線?");
return resultMsg;
}
}
/**
* 退出登入
* @param num
* @return
*/
@GetMapping(path = "/loginout")
public ResultMsg loginOut(Integer num) {
ResultMsg resultMsg = new ResultMsg();
// 獲取當前使用者
Subject subject = SecurityUtils.getSubject();
subject.logout();//退出當前登入
resultMsg.setState(200);
if (num == 1) {
resultMsg.setMsg("已下線!");
} else {
resultMsg.setMsg("當前使用者已退出!");
}
return resultMsg;
}
/**
* 未認證返回登入頁面
* @return
*/
@GetMapping(path = "/login")
public ModelAndView login() {
ModelAndView mv = new ModelAndView("/user/login");
return mv;
}
}
Shiro核心配置
Shiro配置類
ShiroConfig.java
主要建立三大Bean物件
- ShiroFilterFactoryBean(攔截一切請求)3
- DefaultSecurityManager(安全管理器)2
- 自定義Realm 繼承 AuthorizingRealm(主要用於認證和授權)1
建議建立順序逆行
package com.hk.aefz.shiro.config;
@Configuration public class ShiroConfig { // ShiroFliterFactoryBean 3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean( @Qualifier("securityManager") DefaultWebSecurityManager securityManager ) { ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); // 設定安全管理器 factoryBean.setSecurityManager(securityManager); // 新增Shiro內建過濾器
/*
anon:無需認證就可以訪問
authc:必須認證才可以訪問
user:必須擁有記住我功能才可以訪問
perms:擁有對某個資源的許可權才能訪問
role:擁有某個角色許可權才可以訪問
*/ Map<String, String> filterMap = new LinkedHashMap<>(); // 匿名訪問 filterMap.put("/navigation/index","anon"); filterMap.put("/navigation/blogdetails","anon"); filterMap.put("/navigation/login","anon"); filterMap.put("/navigation/register","anon"); // 需要角色 filterMap.put("/navigation/personblog","authc,roles[blogger]"); filterMap.put("/navigation/admin-blog","authc,roles[blogger]"); filterMap.put("/navigation/**","user"); factoryBean.setFilterChainDefinitionMap(filterMap); // 攔截後返回登入頁面 factoryBean.setLoginUrl("/navigation/login");return factoryBean; } // DefaultWebSecurityManager 2 安全管理器 @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager( @Qualifier("userRealm") UserRealm userRealm, ) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 關聯UserRealm securityManager.setRealm(userRealm); return securityManager; } // 建立UserRealm類 需要自定義 1 @Bean public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); return userRealm; } } }
自定義Relam類
繼承AuthorizingRealm類
/** * 自定義UserRealm */ public class UserRealm extends AuthorizingRealm { // 注入AccountController @Autowired private AccountController accountController; @Autowired private UserInfoService userInfoService; @Autowired private AccountService accountService; // 授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.err.println("執行了授權.........");return null; } // 認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.err.println("執行了認證..........."); // 獲取當前登入賬戶 UsernamePasswordToken accountToken = (UsernamePasswordToken) token; String username = accountToken.getUsername(); // 獲取當前賬號 // 連線資料庫進行登入驗證 Account account = accountController.selectByName(username); System.out.println(account); if (account == null) { return null; //丟擲 UnknownAccountException 異常 } // 密碼認證 shiro做 存在洩密 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(account, account.getApassword(), account.getAaccount());return info; } }
測試
使用PostMan進行登入測試