一妇拯、流程圖
ShiroFilter會(huì)攔截用戶發(fā)來(lái)的所有請(qǐng)求针史,然后判斷該請(qǐng)求是否需要做認(rèn)證和授權(quán)羊异,也就是判斷該請(qǐng)求訪問(wèn)的是受限資源還是公共資源,訪問(wèn)受限資源的話就要做認(rèn)證和授權(quán),利用SecurityManager铲咨、Realm做認(rèn)證嘲更、授權(quán)闸溃,認(rèn)證失敗跳轉(zhuǎn)到登錄頁(yè)勋陪,訪問(wèn)公共資源的話直接放行
image
二贪磺、shiro中的過(guò)濾器
image
三、整合步驟
1.引入shiro依賴(lài)
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency>
2.創(chuàng)建自定義Realm類(lèi)
這里面完成認(rèn)證和授權(quán)相關(guān)業(yè)務(wù)
package com.szhedu.springboot_shiro.shiro.realms;
import com.szhedu.springboot_shiro.mapper.UserMapper;
import com.szhedu.springboot_shiro.pojo.User;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Objects;
/**
* 自定義的realm
*/
public class CustomerRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
//授權(quán)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addRole("admin");
authorizationInfo.addStringPermission("user:add:*");
return authorizationInfo;
}
//認(rèn)證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
//查詢數(shù)據(jù)庫(kù)诅愚,如果用戶名和密碼都校驗(yàn)成功寒锚,則認(rèn)證通過(guò)
User user = userMapper.getUser(principal);
if(!Objects.isNull(user)){
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
principal,
user.getPassword(),
//鹽
ByteSource.Util.bytes(user.getSalt()),
this.getName());
return authenticationInfo;
}
return null;
}
}
3.編寫(xiě)shiro配置類(lèi),包含三步①創(chuàng)建ShiroFilter②創(chuàng)建全局安全管理器③創(chuàng)建自定義Realm
package com.szhedu.springboot_shiro.config;
import com.szhedu.springboot_shiro.shiro.realms.CustomerRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* shiro配置類(lèi)
*/
@Configuration
public class ShiroConfig {
//1.創(chuàng)建ShiroFilter
@Bean
public ShiroFilterFactoryBean getShiroFilter(DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
//todo 1. 將全局安全管理器注入
shiroFilter.setSecurityManager(defaultWebSecurityManager);
//todo 2.設(shè)置受限資源
Map<String, String> map = new HashMap<>();
//公共資源先放開(kāi)
map.put("/user/login","anon");
map.put("/user/register","anon");
map.put("/register.jsp","anon");
//authc表示這個(gè)資源需要認(rèn)證和授權(quán)违孝,如果沒(méi)認(rèn)證成功默認(rèn)回到login.jsp
map.put("/**","authc");
shiroFilter.setFilterChainDefinitionMap(map);
return shiroFilter;
}
//2.創(chuàng)建全局安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//將自定義的realm設(shè)置到全局安全管理器中
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
//3.創(chuàng)建自定義Realm
@Bean
public Realm getRealm(){
CustomerRealm customerRealm = new CustomerRealm();
//todo 修改憑證校驗(yàn)匹配器
//這里刹前,就會(huì)先對(duì)用戶輸入的密碼進(jìn)行MD5加密,然后再用加密后的密碼去和數(shù)據(jù)庫(kù)中的密碼做equals判斷
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//使用的算法
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//散列的次數(shù)
hashedCredentialsMatcher.setHashIterations(1024);
customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);
return customerRealm;
}
}
4.登錄接口(認(rèn)證)
//登錄
@PostMapping("/user/login")
public String login(String username,String password){
Subject subject = SecurityUtils.getSubject();
try {
//會(huì)調(diào)用我們自定義的realm類(lèi)進(jìn)行認(rèn)證和授權(quán)
subject.login(new UsernamePasswordToken(username,password));
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用戶名錯(cuò)誤");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密碼錯(cuò)誤");
}
return "redirect:/login.jsp";
}
5.授權(quán):從數(shù)據(jù)庫(kù)查詢登陸用戶的角色信息和所具有的權(quán)限信息雌桑,封裝到SimpleAuthorizationInfo對(duì)象中返回
//授權(quán)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
List<Role> roles = userMapper.getRoles(primaryPrincipal);
if (roles != null){
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
roles.stream().forEach(
role -> {
//封裝角色信息
authorizationInfo.addRole(role.getName());
//封裝權(quán)限信息
List<Perms> perms = userMapper.getPerms(role.getId());
perms.forEach(
perm -> {
authorizationInfo.addStringPermission(perm.getName());
}
);
}
);
return authorizationInfo;
}
return null;
}