springboot整合shiro與自定義過(guò)濾器的全過(guò)程
filter自定義過(guò)濾器 增加了 對(duì)驗(yàn)證碼的校驗(yàn)
package com.youxiong.filter; import com.youxiong.shiro.UsernamePasswordKaptchaToken; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class FormValid extends FormAuthenticationFilter { private String kaptcha = "KAPTCHA_SESSION_KEY"; public FormValid() { super(); } //用戶未登錄 /* @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpSession session = httpServletRequest.getSession(); String kaptchaCode = (String) session.getAttribute(kaptcha); String code = httpServletRequest.getParameter("code"); if(code!=null&&kaptchaCode!=null&&!kaptchaCode.equals(code)){ httpServletRequest.setAttribute("shiroLoginFailure","codeError"); return true; } return super.onAccessDenied(request, response); } */ //用戶提交表單時(shí)候 創(chuàng)建的token @Override protected AuthenticationToken createToken( ServletRequest request, ServletResponse response) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String code = (String) httpServletRequest.getParameter("kaptcha"); String host = getHost(request); String username = getUsername(request); String password = getPassword(request); boolean rememberMe = isRememberMe(request); System.out.println("create token--------------code------>one "+code); return new UsernamePasswordKaptchaToken(username,password.toCharArray(),rememberMe,host,code); } }
自定義UsernamePassword是為了接收前臺(tái)發(fā)送過(guò)來(lái)的數(shù)據(jù)
package com.youxiong.shiro; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import java.io.Serializable; public class UsernamePasswordKaptchaToken extends UsernamePasswordToken { private static final long serialVersionUID = 1L; private String kaptcha; public UsernamePasswordKaptchaToken(){ super(); } public UsernamePasswordKaptchaToken(String username, char[] password, boolean rememberMe, String host, String kaptcha) { super(username, password, rememberMe, host); this.kaptcha = kaptcha; } public String getKaptcha() { return kaptcha; } public void setKaptcha(String kaptcha) { this.kaptcha = kaptcha; } }
shiro配置
package com.youxiong.config; import com.google.code.kaptcha.servlet.KaptchaServlet; import com.youxiong.dao.UserReposisty; import com.youxiong.domain.Permission; import com.youxiong.domain.Role; import com.youxiong.domain.UserInfo; import com.youxiong.filter.FormValid; import com.youxiong.redis.JedisCacheManager; import com.youxiong.redis.RedisSessionDao; import com.youxiong.redis.RedisSessionListener; import com.youxiong.redis.RediseSessionFactory; import com.youxiong.shiro.MyShiroRealm; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.SessionListener; import org.apache.shiro.session.mgt.SessionFactory; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import javax.servlet.Filter; import java.util.*; @Configuration public class ShiroConfig { @Autowired private UserReposisty userReposisty; @Bean public ShiroFilterFactoryBean createShiroFilter(SecurityManager securityManager) { System.out.println("--------ShiroFilterFactoryBean-------"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, Filter> filterMap = new HashMap<>(); //map里面key值要為authc才能使用自定義的過(guò)濾器 filterMap.put("authc", formValid()); // can go to login shiroFilterFactoryBean.setLoginUrl("/login.html"); //doLogin success go to page shiroFilterFactoryBean.setSuccessUrl("/success.html"); //do not Unauthorized page shiroFilterFactoryBean.setUnauthorizedUrl("/403.html"); Map<String, String> map = new LinkedHashMap<String, String>(); //驗(yàn)證碼的路徑 不要跟下面需要認(rèn)證的寫(xiě)在一個(gè)路徑里 會(huì)被攔截的 map.put("/servlet/**", "anon"); //需要把要授權(quán)的URL 全部裝到filterChain中去過(guò)濾 UserInfo userInfo = userReposisty.findByUid(1); for (Role role : userInfo.getRoles()) { for (Permission permission : role.getPermissions()) { if (permission.getUrl() != "") { String permissions = "perms[" + permission.getPermission() + "]"; map.put(permission.getUrl(), permissions); } } } map.put("/user*/*", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); shiroFilterFactoryBean.setFilters(filterMap); return shiroFilterFactoryBean; } //自己定義realm @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); //緩存管理 securityManager.setCacheManager(jedisCacheManager()); //會(huì)話管理 securityManager.setSessionManager(sessionManager()); return securityManager; } //密碼鹽 可以不必實(shí)現(xiàn) 因?yàn)橐话忝艽a可以自己定義自己的密碼加密規(guī)則 /* @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5"); hashedCredentialsMatcher.setHashIterations(2); return hashedCredentialsMatcher; }*/ //開(kāi)啟aop注解 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean(name = "simpleMappingExceptionResolver") public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("DatabaseException", "databaseError");//數(shù)據(jù)庫(kù)異常處理 mappings.setProperty("UnauthorizedException", "403"); r.setExceptionMappings(mappings); // None by default r.setDefaultErrorView("error"); // No default r.setExceptionAttribute("ex"); // Default is "exception" //r.setWarnLogCategory("example.MvcLogger"); // No default return r; } //servlet注冊(cè)器 -----》驗(yàn)證碼的路徑 @Bean public ServletRegistrationBean servletRegistrationBean() { System.out.println("----驗(yàn)證碼---"); return new ServletRegistrationBean(new KaptchaServlet(), "/servlet/kaptcha.jpg"); } //自定義過(guò)濾器 ---》里面實(shí)現(xiàn)了對(duì)驗(yàn)證碼校驗(yàn) @Bean("myFilter") public FormValid formValid() { return new FormValid(); } //jedis緩存 @Bean public JedisCacheManager jedisCacheManager() { return new JedisCacheManager(); } @Bean public SessionManager sessionManager() { DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); defaultWebSessionManager.setSessionIdCookie(simpleCookie()); defaultWebSessionManager.setSessionDAO(sessionDAO()); //可以設(shè)置shiro提供的會(huì)話管理機(jī)制 //defaultWebSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO()); return defaultWebSessionManager; } //這里就是會(huì)話管理的操作類 @Bean public SessionDAO sessionDAO() { return new RedisSessionDao(); } //這里需要設(shè)置一個(gè)cookie的名稱 原因就是會(huì)跟原來(lái)的session的id值重復(fù)的 @Bean public SimpleCookie simpleCookie() { SimpleCookie simpleCookie = new SimpleCookie("REDISSESSION"); return simpleCookie; } }
Shiro中的權(quán)限控制
#需要同時(shí)擁有order:add和order:query權(quán)限才可以訪問(wèn) /order-add = perms["order:add","order:query"] #只需要order:del權(quán)限就可以訪問(wèn) /order-del = perms["order:del"]
perms表示的就是權(quán)限控制,中括號(hào)中就是需要訪問(wèn)等號(hào)之前路徑,需要的權(quán)限名稱。如果在使用Shiro過(guò)濾器的時(shí)候,不配置過(guò)濾器,就會(huì)使用默認(rèn)的過(guò)濾器。
以下是默認(rèn)權(quán)限過(guò)濾器的源碼。
public class PermissionsAuthorizationFilter extends AuthorizationFilter { ? ? public PermissionsAuthorizationFilter() { ? ? } ? ? public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { ? ? ? ? Subject subject = this.getSubject(request, response); ? ? ? ? String[] perms = (String[])mappedValue; ? ? ? ? boolean isPermitted = true; ? ? ? ? if (perms != null && perms.length > 0) { ? ? ? ? ? ? if (perms.length == 1) { ? ? ? ? ? ? ? ? if (!subject.isPermitted(perms[0])) { ? ? ? ? ? ? ? ? ? ? isPermitted = false; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else if (!subject.isPermittedAll(perms)) { ? ? ? ? ? ? ? ? isPermitted = false; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return isPermitted; ? ? } }
從上面的代碼可以看出,我們的配置會(huì)默認(rèn)被強(qiáng)轉(zhuǎn)為string類型的字符串?dāng)?shù)組。當(dāng)只有一個(gè)權(quán)限時(shí),會(huì)直接判斷有沒(méi)有該權(quán)限; 當(dāng)配置多個(gè)權(quán)限時(shí),從下面的代碼可以看出只用在請(qǐng)求url的用戶擁有所有的權(quán)限時(shí),才會(huì)返回true,否則就會(huì)被拒絕訪問(wèn)。
總結(jié)
到此這篇關(guān)于springboot整合shiro與自定義過(guò)濾器的文章就介紹到這了,更多相關(guān)springboot整合shiro與自定義過(guò)濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis分頁(yè)插件PageHelper的分頁(yè)原理剖析
這篇文章主要介紹了Mybatis分頁(yè)插件PageHelper的分頁(yè)原理剖析,PageHelper作為一個(gè)啟動(dòng)器,那么就和其他啟動(dòng)器加載一樣,先讀取spring.factories文件里面配置的類,轉(zhuǎn)成Bean加載本系統(tǒng)中,然后執(zhí)行他的前置后置處理方法,完成初始化,需要的朋友可以參考下2023-08-08httpclient ConnectionHolder連接池連接保持源碼解析
這篇文章主要為大家介紹了httpclient ConnectionHolder連接池連接保持源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11可視化定時(shí)任務(wù)quartz集成解析全過(guò)程
在開(kāi)發(fā)中有很多定時(shí)任務(wù)都不是寫(xiě)死的而是可以人為配置并且寫(xiě)到數(shù)據(jù)庫(kù)中的,下面這篇文章主要給大家介紹了關(guān)于可視化定時(shí)任務(wù)quartz集成解析的相關(guān)資料,需要的朋友可以參考下2022-10-10淺析Spring的事務(wù)實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)介紹了Spring中事務(wù)實(shí)現(xiàn)的原理,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Spring有一定的幫助,需要的可以參考一下2022-11-11地址到經(jīng)緯度坐標(biāo)轉(zhuǎn)化的JAVA代碼
這篇文章介紹了地址到經(jīng)緯度坐標(biāo)轉(zhuǎn)化的JAVA代碼,有需要的朋友可以參考一下2013-09-09Java報(bào)錯(cuò):Error:java:?程序包org.springframework.boot不存在解決辦法
建完springboot項(xiàng)目時(shí),點(diǎn)擊啟動(dòng),有可能會(huì)報(bào)錯(cuò),下面這篇文章主要給大家介紹了關(guān)于Java報(bào)錯(cuò):Error:java:?程序包org.springframework.boot不存在的解決辦法,需要的朋友可以參考下2024-02-02java堆棧類使用實(shí)例(java中stack的使用方法)
java中stack的使用方法,堆棧是一種"后進(jìn)先出"(LIFO) 的數(shù)據(jù)結(jié)構(gòu), 只能在一端進(jìn)行插入(稱為"壓棧") 或刪除 (稱為"出棧")數(shù)據(jù)的操作,下面看示例吧2013-12-12