shiro依賴 shiro-all 及 thymeleaf-extras-shiro
ShiroConfig配置類
package com.qust.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import java.util.HashMap;
import java.util.Map;
/**
* springboot支持註解注入bean,往往用於springboot不集成的第三方組件
*
*/
@Configuration
public class ShiroConfiguration {
/**
* 配置攔截器 請求認證權限 都是靠攔截器
* @param securityManager
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//登錄的url
shiroFilterFactoryBean.setLoginUrl("/loginPage");
//成功後的請求
shiroFilterFactoryBean.setSuccessUrl("/index");
//未授權頁面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
//過濾器
Map<String,String> map = new HashMap<>();
map.put("/loginPage","anon");
map.put("/login","anon");
//anon 無需認證
map.put("/register","anon");
//authc 必須要認證
map.put("/**","authc");
map.put("/addUser","roles[role1]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
/**
* 配置SecurityManager
* @param myRealm
* @return
*/
@Bean(name = "securityManager")
public SecurityManager getSecurityManager(MyRealm myRealm){
SecurityManager securityManager = new DefaultWebSecurityManager(myRealm);
return securityManager;
}
/**
* 創建自定義realm
* @return
*/
@Bean(name = "myRealm")
public MyRealm getMyRealm(){
return new MyRealm();
}
/**
* 配置shiro和thymelf進行整合
* @return
*/
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
自定義MyRealm
package com.qust.config;
import com.qust.entity.Role;
import com.qust.service.TeacherService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class MyRealm extends AuthorizingRealm {
@Autowired
private TeacherService teacherService;
public TeacherService getTeacherService() {
return teacherService;
}
public void setTeacherService(TeacherService teacherService) {
this.teacherService = teacherService;
}
/**
* 授權
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//只有通過認證後 纔可以考慮授權的問題 獲取到認證後返回的信息
SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
//獲取用戶名
String username = getAvailablePrincipal(principalCollection).toString();
//通過用戶名 獲取該用戶有的角色
List<Role> roles = teacherService.getRoleByName(username);
for (Role role1 : roles) {
sai.addRole(role1.getRname());
}
//通過用戶名獲取擁有的權限
List<Permission> permission = userService.getPermissionByName(username);
for (Permission permission1 : permission) {
sai.addStringPermission(permission1.getPname());
}
return sai;
}
/**
* 認證
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//獲取令牌
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//username是肯定相同的 比較密碼
String account = teacherService.queryPwdByName(token.getUsername());
if(account != null){
//三個參數(用戶名、密碼、本realm名字)
return new SimpleAuthenticationInfo(token.getUsername(),account,getName());
}
return null;
}
}
Controller層
@PostMapping("/login")
public String login(String username, String password, Model model){
String pass = new Md5Hash(password).toString();
//創建令牌 將前端傳過來的用戶名、密碼放進令牌
UsernamePasswordToken token = new UsernamePasswordToken(username,pass);
try {
//通過SecurityUtils 獲取用戶主體
Subject subject = SecurityUtils.getSubject();
//將登錄交給SecurityManager進行管理
subject.login(token);
//將信息存入session
// subject.getSession().setAttribute("account",account);
//判斷登錄的主體是否有user角色
boolean user = subject.hasRole("user");
//判斷登錄的主題是否有該權限
boolean add = subject.isPermitted("add");
return "index";
} catch (UnknownAccountException e) {
model.addAttribute("msg","用戶名錯誤");
return "login";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg", "密碼錯誤");
return "login";
}
}
認證流程圖
授權流程圖