springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程
生活随笔
收集整理的這篇文章主要介紹了
springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
springboot項目中使用shiro 自定義過濾器和token的方式
實現(xiàn)步驟主要是以下幾步:
1. 在項目中導(dǎo)入maven依賴
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency>2. shiro的核心配置類和代碼
3. 自定義的認(rèn)證源
package com.ratel.fast.modules.sys.oauth2; import com.ratel.fast.modules.sys.service.ShiroService; import com.ratel.fast.modules.sys.entity.SysUserEntity; import com.ratel.fast.modules.sys.entity.SysUserTokenEntity; import com.ratel.fast.modules.sys.service.ShiroService; import org.apache.shiro.authc.*; 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.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Set;/*** 認(rèn)證***/ @Component public class OAuth2Realm extends AuthorizingRealm {@Autowiredprivate ShiroService shiroService;@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof OAuth2Token;}/*** 授權(quán)(驗證權(quán)限時調(diào)用)* 前端在請求帶@RequiresPermissions注解 注解的方法時會調(diào)用 doGetAuthorizationInfo 這個方法*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();Long userId = user.getUserId();//用戶權(quán)限列表Set<String> permsSet = shiroService.getUserPermissions(userId);SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setStringPermissions(permsSet);return info;}/*** 認(rèn)證(登錄時調(diào)用)* 每次請求的時候都會調(diào)用這個方法驗證token是否失效和用戶是否被鎖定*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String accessToken = (String) token.getPrincipal();//根據(jù)accessToken,查詢用戶信息SysUserTokenEntity tokenEntity = shiroService.queryByToken(accessToken);//token失效if(tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()){throw new IncorrectCredentialsException("token失效,請重新登錄");}//查詢用戶信息SysUserEntity user = shiroService.queryUser(tokenEntity.getUserId());//賬號鎖定if(user.getStatus() == 0){throw new LockedAccountException("賬號已被鎖定,請聯(lián)系管理員");}SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName());return info;} }4. 自定義的過濾器
package com.ratel.fast.modules.sys.oauth2;import com.google.gson.Gson; import com.ratel.fast.common.utils.HttpContextUtils; import com.ratel.fast.common.utils.R; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpStatus; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;/*** oauth2過濾器***/ public class OAuth2Filter extends AuthenticatingFilter {@Overrideprotected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {//獲取請求tokenString token = getRequestToken((HttpServletRequest) request);if(StringUtils.isBlank(token)){return null;}return new OAuth2Token(token);}/*** 判斷用戶是否已經(jīng)登錄,* 如果是options的請求則放行,否則進(jìn)行調(diào)用onAccessDenied進(jìn)行token認(rèn)證流程* @param request* @param response* @param mappedValue* @return*/@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {if(((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())){return true;}return false;}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {//獲取請求token,如果token不存在,直接返回401String token = getRequestToken((HttpServletRequest) request);if(StringUtils.isBlank(token)){HttpServletResponse httpResponse = (HttpServletResponse) response;httpResponse.setHeader("Access-Control-Allow-Credentials", "true");httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());String json = new Gson().toJson(R.error(HttpStatus.SC_UNAUTHORIZED, "invalid token"));httpResponse.getWriter().print(json);return false;}return executeLogin(request, response);}@Overrideprotected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {HttpServletResponse httpResponse = (HttpServletResponse) response;httpResponse.setContentType("application/json;charset=utf-8");httpResponse.setHeader("Access-Control-Allow-Credentials", "true");httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());try {//處理登錄失敗的異常Throwable throwable = e.getCause() == null ? e : e.getCause();R r = R.error(HttpStatus.SC_UNAUTHORIZED, throwable.getMessage());String json = new Gson().toJson(r);httpResponse.getWriter().print(json);} catch (IOException e1) {}return false;}/*** 獲取請求的token*/private String getRequestToken(HttpServletRequest httpRequest){//從header中獲取tokenString token = httpRequest.getHeader("token");//如果header中不存在token,則從參數(shù)中獲取tokenif(StringUtils.isBlank(token)){token = httpRequest.getParameter("token");}return token;}}5. 核心配置類
package com.ratel.fast.config;import com.ratel.fast.modules.sys.oauth2.OAuth2Filter; import com.ratel.fast.modules.sys.oauth2.OAuth2Realm; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 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 javax.servlet.Filter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map;/*** Shiro配置***/ @Configuration public class ShiroConfig {@Bean("securityManager")public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(oAuth2Realm);securityManager.setRememberMeManager(null);return securityManager;}/*** 這個bean的名字必須叫 shiroFilter ,否則啟動的時候會報錯* @Bean ("shiroFilter") 之后的括號可以不用寫,spring默認(rèn)方法名為的bean的名字* @param securityManager* @return*/@Bean("shiroFilter")public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();shiroFilter.setSecurityManager(securityManager);//oauth過濾Map<String, Filter> filters = new HashMap<>();//添加自定義過濾器filters.put("oauth2", new OAuth2Filter());shiroFilter.setFilters(filters);Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/webjars/**", "anon");filterMap.put("/druid/**", "anon");filterMap.put("/app/**", "anon");filterMap.put("/sys/login", "anon");filterMap.put("/swagger/**", "anon");filterMap.put("/v2/api-docs", "anon");filterMap.put("/swagger-ui.html", "anon");filterMap.put("/swagger-resources/**", "anon");filterMap.put("/captcha.jpg", "anon");filterMap.put("/aaa.txt", "anon");//使用自定義過濾器攔截除上邊以外的所有請求filterMap.put("/**", "oauth2");shiroFilter.setFilterChainDefinitionMap(filterMap);return shiroFilter;}@Bean("lifecycleBeanPostProcessor")public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}}6. 用戶token類 (用于往數(shù)據(jù)庫中存儲的時候用)
package com.ratel.fast.modules.sys.entity;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; import java.util.Date;/*** 系統(tǒng)用戶Token***/ @Data @TableName("sys_user_token") public class SysUserTokenEntity implements Serializable {private static final long serialVersionUID = 1L;//用戶ID@TableId(type = IdType.INPUT)private Long userId;//tokenprivate String token;//過期時間private Date expireTime;//更新時間private Date updateTime;}到此我們已經(jīng)完成了shiro的認(rèn)證過程的代碼。
記住一點,Shiro 不會去維護(hù)用戶、維護(hù)權(quán)限;這些需要我們自己去設(shè)計 / 提供;然后通過相應(yīng)的接口注入給 Shiro 即可。
shiro使用token登錄流程
總結(jié)
以上是生活随笔為你收集整理的springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神经信息学整理(2)-caianiell
- 下一篇: vb.net 机器学习-候选消除法