SpringBoot入門,整合shiro許可權管理
阿新 • • 發佈:2019-01-22
引言
本文繼續沿用上幾篇部落格的基礎,在此之上整合Shiro,實現許可權管理,具體環境搭建,請參考我之前的部落格,在這裡不做贅述。
1.引入Shrio依賴
pom檔案下新增shiro依賴
<!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
2.配置shiro
在工程目錄下新建一個config包用來存放Shrio配置類,新建一個ShiroConfig.java和CustomRealm.java兩個類,具體程式碼如下:
package com.example.config.shiro; import org.apache.shiro.mgt.SecurityManager; 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.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ ShiroFilterFactoryBean shiroBean = new ShiroFilterFactoryBean(); //必須設定SecurityManager shiroBean.setSecurityManager(securityManager); //設定登入介面的url shiroBean.setLoginUrl("/backend/"); //設定登入成功後跳轉的url shiroBean.setSuccessUrl("/backend/home"); //設定無許可權時跳轉的url shiroBean.setUnauthorizedUrl("/backend/"); //攔截器 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //可以直接訪問的連線,不攔截 filterChainDefinitionMap.put("/backend/","anon"); filterChainDefinitionMap.put("/backend/login","anon"); filterChainDefinitionMap.put("/css/**","anon"); filterChainDefinitionMap.put("/js/**","anon"); filterChainDefinitionMap.put("/img/**","anon"); filterChainDefinitionMap.put("/frontend/**","anon"); //退出過濾器,shiro幫我們實現 filterChainDefinitionMap.put("/logout","logout"); //其餘介面一律攔截,需要認證 filterChainDefinitionMap.put("/backend/**","authc"); shiroBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroBean; } @Bean public SecurityManager securityManager(CustomRealm customRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(customRealm); return securityManager; } @Bean public CustomRealm customRealm(){ CustomRealm customRealm = new CustomRealm(); return customRealm; } }
注意:上面的攔截地址需要自己根據實際情況手動配置,我這裡只是根據我的專案進行的簡單配置,許可權設定的順序應從上到下,由小到大。
shiro常用認證引數如下,具體其他引數,請查閱官方文件。
anno | 不需要認證就可直接訪問 |
authc | 認證後才可訪問 |
roles | 擁有某角色後才可以使用 |
logout | shiro幫我們實現的退出 |
package com.example.config.shiro; import com.example.bean.Manager; import com.example.bean.User; import com.example.dao.ManagerMapper; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; public class CustomRealm extends AuthorizingRealm { @Autowired private ManagerMapper managerMapper; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); Manager manager = managerMapper.findManagerByName(username); if(manager == null){ throw new AuthenticationException("使用者名稱不存在!"); } AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(token.getPrincipal(),manager.getPassword(),this.getName()); super.clearCachedAuthenticationInfo(authcInfo.getPrincipals()); SecurityUtils.getSubject().getSession().setAttribute("manager",manager); return authcInfo ; } }
這裡我們自定義處理登陸認證。ManagerMapper使我們自定義的一張登陸表,屬性如下,建立完後使用mybatis-generator逆向工程生成就可以了。
id | int |
---|---|
username | varchar |
password | varchar |
3.測試
新建LoginController類,並處理登陸/退出請求
package com.example.controller;
import com.example.bean.Manager;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/backend")
public class LoginController {
@PostMapping("/login")
public String login(Model model, Manager manager, HttpServletResponse response){
if (manager==null){
return "backend/index";
}
String username = manager.getUsername();
String password = manager.getPassword();
UsernamePasswordToken token = new UsernamePasswordToken(username,password,false);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch(IncorrectCredentialsException e){
model.addAttribute("errPassword", "密碼錯誤!");
return "backend/index";
} catch (AuthenticationException e){
model.addAttribute("errAccount",e.getMessage());
return "backend/index";
}
try {
response.sendRedirect("/backend/home");
return null;
} catch (IOException e) {
return "backend/main/index";
}
}
@GetMapping("/logout")
public String logout(HttpServletResponse response){
try {
SecurityUtils.getSubject().logout();
}catch (Exception e){
System.out.println(e.getMessage());
}
try {
response.sendRedirect("/backend/home");
return null;
} catch (IOException e) {
return "backend/index";
}
}
}
前端頁面這裡就不上程式碼了自行解決。之後我們就可以進行試驗,如果輸入的網頁地址是登陸介面,不需要認證,那麼我們就可以直接訪問,而輸入其他地址時,因需要認證操作,所以無法訪問被拒接,跳轉到我們預先設定好的登陸介面。登陸成功後跳轉到home介面,由於在CustomRealm 中認證成功後我們將登陸資訊放在了session中,因此我們可以在home介面中獲取到登陸使用者的資訊。最後在home介面內新增退出的連線,呼叫controller中的logout方法,實現退出後跳轉到登陸介面。
至此,springboot整合shiro就完成了,可能說的比較簡短,但是核心的程式碼我基本已經給全,剩下少量操作需要你自己完成。如果有什麼問題,可以跟我聯絡。歡迎大家批評指正,一起學習,一起進步。