網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、Shiro
????????Shiro是一個(gè)強(qiáng)大而靈活的開(kāi)源安全框架,,執(zhí)行身份驗(yàn)證、授權(quán)、密碼和會(huì)話管理。使用Shiro易于理解的API,可以快速、輕松地獲得任何應(yīng)用程序,從最小的移動(dòng)應(yīng)用程序到最大的網(wǎng)絡(luò)和企業(yè)應(yīng)用程序。(和Spring?Security,Shiro在保持強(qiáng)大功能的同時(shí),還在簡(jiǎn)單性和靈活性方面擁有巨大優(yōu)勢(shì))
三個(gè)核心組件:Subject, SecurityManager 和 Realms
Subject:是“當(dāng)前操作用戶”。但是,在Shiro中,Subject這一概念并不僅僅指人,也可以是第三方進(jìn)程、后臺(tái)帳戶(Daemon?Account)或其他類(lèi)似事物。它僅僅意味著“當(dāng)前跟軟件交互的東西”。Subject代表了當(dāng)前用戶的安全操作,SecurityManager則管理所有用戶的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過(guò)SecurityManager來(lái)管理內(nèi)部組件實(shí)例,并通過(guò)它來(lái)提供安全管理的各種服務(wù)。
Realm:?Realm充當(dāng)了Shiro與應(yīng)用安全數(shù)據(jù)間的“橋梁”或者“連接器”。也就是說(shuō),當(dāng)對(duì)用戶執(zhí)行認(rèn)證(登錄)和授權(quán)(訪問(wèn)控制)驗(yàn)證時(shí),Shiro會(huì)從應(yīng)用配置的Realm中查找用戶及其權(quán)限信息。
從這個(gè)意義上講,Realm實(shí)質(zhì)上是一個(gè)安全相關(guān)的DAO:它封裝了數(shù)據(jù)源的連接細(xì)節(jié),并在需要時(shí)將相關(guān)數(shù)據(jù)提供給Shiro。當(dāng)配置Shiro時(shí),你必須至少指定一個(gè)Realm,用于認(rèn)證和(或)授權(quán)。配置多個(gè)Realm是可以的,但是至少需要一個(gè)。
Shiro內(nèi)置了可以連接大量安全數(shù)據(jù)源(又名目錄)的Realm,如LDAP、關(guān)系數(shù)據(jù)庫(kù)(JDBC)、類(lèi)似INI的文本配置資源以及屬性文件等。如果系統(tǒng)默認(rèn)的Realm不能滿足需求,你還可以插入代表自定義數(shù)據(jù)源的自己的Realm實(shí)現(xiàn)。
實(shí)現(xiàn)代碼:
坐標(biāo):
<!--shiro和spring整合-->
<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>
創(chuàng)建realm
@Configuration
public class ShiroConfiguration {
//1.創(chuàng)建realm
@Bean
public CustomRealm getRealm() {
return new CustomRealm();
}
//2.創(chuàng)建安全管理器
@Bean
public SecurityManager getSecurityManager(CustomRealm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
//3.配置shiro的過(guò)濾器工廠再web程序中,shiro進(jìn)行權(quán)限控制全部是通過(guò)一組過(guò)濾器集合進(jìn)行控制
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
//1.創(chuàng)建過(guò)濾器工廠
ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
//2.設(shè)置安全管理器
filterFactory.setSecurityManager(securityManager);
//3.通用配置(跳轉(zhuǎn)登錄頁(yè)面,為授權(quán)跳轉(zhuǎn)的頁(yè)面)
filterFactory.setLoginUrl("/autherror");//跳轉(zhuǎn)url地址
//4.設(shè)置過(guò)濾器集合
//key = 攔截的url地址
//value = 過(guò)濾器類(lèi)型
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/login","anon");//當(dāng)前請(qǐng)求地址可以匿名訪問(wèn)
filterMap.put("/user/**","authc");//當(dāng)前請(qǐng)求地址必須認(rèn)證之后可以訪問(wèn)
//在過(guò)濾器工程內(nèi)設(shè)置過(guò)濾器
filterFactory.setFilterChainDefinitionMap(filterMap);
return filterFactory;
}
//開(kāi)啟對(duì)shior注解的支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
//啟對(duì)shior注解的支持2
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator app=new DefaultAdvisorAutoProxyCreator();
app.setProxyTargetClass(true);
return app;
}
}
認(rèn)證和授權(quán)方法
public class CustomRealm extends AuthorizingRealm {
public void setName(String name) {
super.setName("customRealm");
}
@Autowired
private UserService userService;
/**
* 授權(quán)方法
* 操作的時(shí)候,判斷用戶是否具有響應(yīng)的權(quán)限
* 一定先認(rèn)證再授權(quán)
* 先認(rèn)證 -- 安全數(shù)據(jù)
* 再授權(quán) -- 根據(jù)安全數(shù)據(jù)獲取用戶具有的所有操作權(quán)限
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//1.獲取已認(rèn)證的用戶數(shù)據(jù)
User user = (User) principalCollection.getPrimaryPrincipal();//得到唯一的安全數(shù)據(jù)
//2.根據(jù)用戶數(shù)據(jù)獲取用戶的權(quán)限信息(所有角色,所有權(quán)限)
Set<String> roles = new HashSet<>();//所有角色
Set<String> perms = new HashSet<>();//所有權(quán)限
for (Role role : user.getRoles()) {
roles.add(role.getName());
for (Permission perm : role.getPermissions()) {
perms.add(perm.getCode());
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setStringPermissions(perms);
info.setRoles(roles);
return info;
}
/**
* 認(rèn)證方法
* 參數(shù):傳遞的用戶名密碼
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.獲取登錄的用戶名密碼(token)
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
String username = upToken.getUsername();//用戶錄入的賬號(hào)
//2.根據(jù)用戶名查詢(xún)數(shù)據(jù)庫(kù)
//mybatis情景下:user對(duì)象中包含ID,name,pwd(匿名)
//JPA情景下:user對(duì)象中包含ID,name,pwd(匿名),set<角色>,set<權(quán)限>
User user = userService.findByName(username);
//3.判斷用戶是否存在或者密碼是否一致
if(user != null) {
//4.如果一致返回安全數(shù)據(jù)
//構(gòu)造方法:安全數(shù)據(jù),密碼(匿名),混淆字符串(salt),realm域名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
return info;
}
//5.不一致,返回null(拋出異常)
return null;
}
/**
* 自定義密碼比較器
*/
@PostConstruct
public void initCredentialsMatcher() {
//指定密碼算法
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
//指定迭代次數(shù)
hashedCredentialsMatcher.setHashIterations(DigestsUtil.COUNTS);
//生效密碼比較器
setCredentialsMatcher(hashedCredentialsMatcher);
}
}
密碼加密
public class DigestsUtil {
//加密方式
public static final String SHA1 = "SHA-1";
//循環(huán)次數(shù)
public static final Integer COUNTS =520;
public static String sha1(String input, String salt) {
return new SimpleHash(SHA1, input, salt,COUNTS).toString();
}
// 隨機(jī)獲得salt字符串
public static String generateSalt(){
SecureRandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
return randomNumberGenerator.nextBytes().toHex();
}
//生成密碼字符密文和salt密文
public static Map<String,String> entryptPassword(String passwordPlain) {
Map<String,String> map = new HashMap<>();
String salt = generateSalt();
String password =sha1(passwordPlain,salt);
map.put("salt", salt);
map.put("password", password);
return map;
}
}
二、Spring?Security
????????Spring?Security是一個(gè)能夠?yàn)榛?span style="color:#ff9900;">Spring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問(wèn)控制解決方案的安全框架。它提供了一組可以在Spring應(yīng)用上下文中配置的Bean,充分利用了Spring?IoC,DI(控制反轉(zhuǎn)Inversion?of?Control?,DI:Dependency?Injection?依賴(lài)注入)和AOP(面向切面編程)功能,為應(yīng)用系統(tǒng)提供聲明式的安全訪問(wèn)控制功能,減少了為企業(yè)系統(tǒng)安全控制編寫(xiě)大量重復(fù)代碼的工作。(除了不能脫離Spring,shiro的功能它都有。而且Spring Security對(duì)Oauth、OpenID也有支持,Shiro則需要自己手動(dòng)實(shí)現(xiàn)。Spring Security的權(quán)限細(xì)粒度更高)
實(shí)現(xiàn)代碼:坐標(biāo)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Configuration //就相當(dāng)于springmvc.xml文件
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//訪問(wèn)登陸頁(yè)面,安全框架所提供的
registry.addViewController("/loginPage").setViewName("login");
}
}
安全攔截機(jī)制(重點(diǎn))
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 定義用戶信息服務(wù)(查詢(xún)用戶信息)
* 方式1:通過(guò)內(nèi)存定義
* 方式2:查詢(xún)數(shù)據(jù)庫(kù)
*/
@Bean //密碼編碼器
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//安全攔截機(jī)制(最重要)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //關(guān)閉csrf防火墻,避免csrf現(xiàn)象
.authorizeRequests() //所有請(qǐng)求
.antMatchers("/r/r1").hasAuthority("p1")
//訪問(wèn)/r/r1資源的 url需要擁有p1權(quán)限。
.antMatchers("/r/r2").hasAuthority("p2")
//訪問(wèn)/r/r2資源的 url需要擁有p2權(quán)限
.antMatchers("/r/**").authenticated()
//所有/r/**的請(qǐng)求必須認(rèn)證通過(guò)
.anyRequest().permitAll()
//除了/r/**,其它的請(qǐng)求可以訪問(wèn)
.and()
.formLogin()
.loginPage("/loginPage") //允許表單登錄
.loginProcessingUrl("/doLogin") //登錄的提交接口
.successForwardUrl("/login-success"); //自定義登錄成功的頁(yè)面地址
}
}
啟動(dòng)類(lèi)注解
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@ServletComponentScan
public class SecuritySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(SecuritySpringBootApp.class,args);
}
授權(quán)注解
@GetMapping(value = "/r/r1")
@PreAuthorize("hasAuthority('user-find')")//擁有p1權(quán)限才可以訪問(wèn)
public String r1(){
return " 訪問(wèn)資源1";
}
總結(jié):? ? ?
相同點(diǎn):
1.其核心都是一組過(guò)濾器鏈。
2.認(rèn)證功能
3.授權(quán)功能
4.加密功能
5.會(huì)話管理
6.緩存支持
7.rememberMe功能
區(qū)別:
1.Spring?Security是一個(gè)重量級(jí)的安全管理框架;Shiro則是一個(gè)輕量級(jí)的安全管理框架
2.Spring?Security?基于Spring開(kāi)發(fā),項(xiàng)目若使用Spring作為基礎(chǔ),配合Spring?Security?做權(quán)限更便捷,而Shiro需要和Spring?進(jìn)行整合開(kāi)發(fā);
3.Spring?Security?功能比Shiro更加豐富些,例如安全維護(hù)方面;
4.Spring?Security?社區(qū)資源相對(duì)于Shiro更加豐富;
5.Shiro?的配置和使用比較簡(jiǎn)單,Spring?Security?上手復(fù)雜些;
6.Shiro?依賴(lài)性低,不需要任何框架和容器,可以獨(dú)立運(yùn)行,?Spring?Security依賴(lài)Spring容器;
7.Shiro?不僅僅可以使用在web中,它可以工作在任何應(yīng)用環(huán)境中。在集群會(huì)話時(shí)Shiro最重要的一個(gè)好處或許就是它的會(huì)話是獨(dú)立于容器的;
Shiro有很多地方都比Spring Security方便簡(jiǎn)單直接,比起Spring Security的龐大模式更容易理解和切入一些,而Spring Security比Shiro功能上要多一點(diǎn),再就是和spring框架的無(wú)縫對(duì)接,比如支持spel等,有時(shí)候比Shiro更方便靈活。
原文鏈接:https://blog.csdn.net/l1050188952/article/details/126693947
相關(guān)推薦
- 2022-10-02 C++?電話號(hào)碼的字母組合功能實(shí)現(xiàn)_C 語(yǔ)言
- 2024-01-05 IDEA創(chuàng)建導(dǎo)入Maven工程時(shí)出錯(cuò)Connection refused to host
- 2021-12-09 帶你一文了解C#中的LINQ_C#教程
- 2022-05-24 C#多線程TPL模式下使用HttpClient_C#教程
- 2022-11-03 tomcat?集群監(jiān)控與彈性伸縮詳解_Tomcat
- 2022-04-25 C#關(guān)于Func和Action委托的介紹詳解_C#教程
- 2022-06-14 C語(yǔ)言選擇、循環(huán)、函數(shù)、數(shù)組與操作符_C 語(yǔ)言
- 2022-09-03 機(jī)器學(xué)習(xí)數(shù)據(jù)預(yù)處理之獨(dú)熱One-Hot編碼及其代碼詳解_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支