欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

如何使用SpringBoot+Shiro實現權限管理

這篇文章主要介紹如何使用Spring Boot+Shiro實現權限管理,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯公司主營大東網站建設的網絡公司,主營網站建設方案,成都App制作,大東h5小程序制作搭建,大東網站營銷推廣歡迎大東等地區(qū)企業(yè)咨詢

一:配置pom.xml文件

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0</version>
		</dependency>

二:ShiroConfig配置類

@Configuration
public class ShiroConfig {
	@Bean("sessionManager")
	public SessionManager sessionManager() {
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(24 * 60 * 60 * 1000);
		// 開啟會話驗證器
		sessionManager.setSessionValidationSchedulerEnabled(true);
		// 刪除失效的session
		sessionManager.setDeleteInvalidSessions(true);
		// 指定sessionId,使用默認的“JSESSIONID”
		sessionManager.setSessionIdCookieEnabled(true);
		return sessionManager;
	}
	/** 
	  * 我們在使用shiro的時候,首先都會先初始化SecurityManager,
	  * 然后往SecurityManager中注入shiro的其他組件,像sessionManager、realm等。
	 */
	@Bean("securityManager")
	public SecurityManager securityManager(OAuth3Realm oAuth3Realm, SessionManager sessionManager) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(oAuth3Realm);
		securityManager.setSessionManager(sessionManager);
		return securityManager;
	}
	@Bean("shiroFilter")
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		shiroFilter.setSecurityManager(securityManager);
		// oauth過濾
		Map<String, Filter> filters = new HashMap<>();
		filters.put("oauth3", new OAuth3Filter());
		shiroFilter.setFilters(filters);
		// 配置可以匿名訪問的地址,可以根據實際情況自己添加,放行一些靜態(tài)資源等,anon 表示放行
		Map<String, String> filterMap = new LinkedHashMap<>();
		filterMap.put("/webjars/**", "anon");
		filterMap.put("/druid/**", "anon");
		filterMap.put("/app/**", "anon");
		filterMap.put("/file/**", "anon");
		filterMap.put("/shiro/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");
		// 其它通過自定義的OAuth3Filter進行過濾
		filterMap.put("/**", "oauth3");
		shiroFilter.setFilterChainDefinitionMap(filterMap);
		return shiroFilter;
	}
	@Bean("lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}
	/**
	  * @Title: defaultAdvisorAutoProxyCreator
	  * @Description: 掃描上下文,尋找所有的Advistor(通知器),將這些Advisor應用到所有符合切入點的Bean中
	  * @return   Spring的一個bean,由Advisor決定對哪些類的方法進行AOP代理。
	  * @return DefaultAdvisorAutoProxyCreator    返回類型
	  * @throws
	  */
//	@Bean
//	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
//		DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
//		proxyCreator.setProxyTargetClass(true);
//		return proxyCreator;
//	}
	/**
	  * @Title: authorizationAttributeSourceAdvisor
	  * @Description: 開啟shiro aop注解支持
	  * @param securityManager
	  * @return   參數說明
	  * @return AuthorizationAttributeSourceAdvisor    返回類型
	  * @throws
	  */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}
}

其中,如果啟用了DefaultAdvisorAutoProxyCreator的話,會導致二次代理的問題,Realm中的doGetAuthorizationInfo會重復調用2次。

三:自定義Shiro Filter類OAuth3Filter

public class OAuth3Filter extends AuthenticatingFilter {
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        //獲取請求token
        String token = getRequestToken((HttpServletRequest) request);
        if(StringUtils.isNullOrEmpty(token)){
            return null;
        }
        return new OAuth3Token(token);
    }
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //現在vue項目中使用axios發(fā)送http請求,每次請求都會多一次Request Method: OPTIONS請求,稱為“預檢”請求
    	if(((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())){
            return true;
        }
        return false;
    }
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //獲取請求token,如果token不存在,直接返回401
        String token = getRequestToken((HttpServletRequest) request);
        if(StringUtils.isNullOrEmpty(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);
    }
    @Override
    protected 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中獲取token
        String token = httpRequest.getHeader("token");
        //如果header中不存在token,則從參數中獲取token
        if(StringUtils.isNullOrEmpty(token)){
            token = httpRequest.getParameter("token");
        }
        return "112233445566";//token;
    }
}

對于復雜的跨域請求,Vue會首先發(fā)送一個OPTIONS請求,進行驗證。需要后端對所有接口統一處理放行OPTIONS方法(即返回200)即可

四:自定義Token

public class OAuth3Token implements AuthenticationToken {
	private String token;
	public OAuth3Token(String token) {
		this.token = token;
	}
	/*
	 * 登錄提交的用戶名
	 * 
	 */
	@Override
	public String getPrincipal() {
		return token;
	}
	/*
	 * 只被Subject 知道的秘密值,比如我們登錄提供的密碼
	 * 
	 */
	@Override
	public Object getCredentials() {
		return token;
	}
}

五:自定義OAuth3Realm

@Component
public class OAuth3Realm extends AuthorizingRealm {
	@Autowired
	private ShiroService shiroService;
	/*
	 * 判斷此Realm是否支持此Token
	 */
	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof OAuth3Token;
	}
	/*
	 * 提供用戶信息返回權限信息 
	 * 
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		System.out.println("=============獲取已登錄用戶,權限信息============");
		
		SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal();
		Long userId = user.getUserId();
		// 用戶權限列表
		Set<String> permsSet = shiroService.getUserPermissions(userId);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(permsSet);
		return info;
	}
	/*
	 * 根據token獲取認證信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("=============獲取已登錄用戶,用戶信息============");
		String accessToken = (String) token.getPrincipal();
		// 根據accessToken,查詢用戶信息
		SysUserTokenEntity tokenEntity = shiroService.queryByToken(accessToken);
		// token失效
		if (tokenEntity == null) {
			throw new IncorrectCredentialsException("token失效,請重新登錄");
		}
		// 查詢用戶信息
		SysUserEntity user = shiroService.queryUser(tokenEntity.getUserId());
		// 賬號鎖定
		if (user.getStatus().equals("00")) {
			throw new LockedAccountException("賬號已被鎖定,請聯系管理員");
		}
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName() // 返回一個唯一的Realm名字
		);
		return info;
	}
}

shiroService用來從數據庫或者緩存中,查詢用戶信息和權限信息。

六:TokenGenerator

public class TokenGenerator {
    public static String generateValue() {
        return generateValue(UUID.randomUUID().toString());
    }
    private static final char[] hexCode = "0123456789abcdef".toCharArray();
    public static String toHexString(byte[] data) {
        if(data == null) {
            return null;
        }
        StringBuilder r = new StringBuilder(data.length*2);
        for ( byte b : data) {
            r.append(hexCode[(b >> 4) & 0xF]);
            r.append(hexCode[(b & 0xF)]);
        }
        return r.toString();
    }
    public static String generateValue(String param) {
        try {
            MessageDigest algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(param.getBytes());
            byte[] messageDigest = algorithm.digest();
            return toHexString(messageDigest);
        } catch (Exception e) {
           e.printStackTrace();
        }
        return "";
    }
}

七:Controller層Demo

@RestController
@RequestMapping("shiro")
public class ShiroController {
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login() {
		return "login";
	}
	@RequestMapping(value = "/info", method = RequestMethod.GET)
	@RequiresPermissions("sys:config:info")
	public String info() {
		return "info";
	}
}

八:登錄代碼

	@PostMapping("/sys/login")
	public Map<String, Object> login(@RequestBody SysLoginForm form)throws IOException {
		boolean captcha = captchaService.validate(form.getUuid(), form.getCaptcha());
		if(!captcha){
			return R.error("驗證碼不正確");
		}
		//用戶信息
		SysUserEntity user = sysUserService.queryByUserName(form.getUsername());
		//賬號不存在、密碼錯誤
		if(user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
			return R.error("賬號或密碼不正確");
		}
		//賬號鎖定
		if(Constant.CommonStatus.BANNED.getValue().equals(user.getStatus())){
			return R.error("賬號已被鎖定,請聯系管理員");
		}
		//生成token,并保存到數據庫
		R r = sysUserTokenService.createToken(user.getUserId());
		return r;
	}

登錄驗證,獨立實現,驗證成功后創(chuàng)建Token,Token放到redis緩存中。前端頁面請求接口時要帶Token.

九:代碼調用流程

如何使用Spring Boot+Shiro實現權限管理

1.登錄成功后,創(chuàng)建Token,后面的接口調用都要傳遞Token

2.接口首先通過shiroFilter過濾,確定是否要進入OAuth3Filter進行處理

3.OAuth3Filter 首先執(zhí)行isAccessAllowed方法,如果時OPTIONS請求直接放行,否則進行Shiro的executeLogin驗證

4.executeLogin執(zhí)行的時候會到OAuth3Realm中調用doGetAuthenticationInfo方法,根據Token獲取當前登錄用戶的信息(Token與用戶的關聯,已在第八點自己實現的登錄代碼中實現)

5.executeLogin成功后,會看當前訪問的接口,有無權限注解@RequiresPermissions

6.如果有注解的話,說需要進行權限驗證,Shiro會通過OAuth3Realm的doGetAuthorizationInfo方法,獲取當前用戶的權限進行驗證

以上是“如何使用Spring Boot+Shiro實現權限管理”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注創(chuàng)新互聯行業(yè)資訊頻道!

當前文章:如何使用SpringBoot+Shiro實現權限管理
標題路徑:http://aaarwkj.com/article48/jpoihp.html

成都網站建設公司_創(chuàng)新互聯,為您提供移動網站建設、網站收錄定制開發(fā)企業(yè)建站、App設計、小程序開發(fā)

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

網站建設網站維護公司
国产午夜福利片新视觉| 亚洲精品免费一区二区三区| 日本熟女中文字幕一区| 亚洲另类偷拍校园伦理| 打开网址国语一级黄色片| 日韩精品一区二区在 | 日韩人妻中出中文字幕| 成人黄色18免费网站| 亚洲免费av一区二区| 欧美日韩国产免费电影| 国产激情久久久久久久久久久| 国产极品美女视频福利| 人妇乱系列中文字幕人妻| 欧美日韩在线一区二区精品| 中文字幕加勒比东京热| 国内精品自产拍久久久久久久久91| 色综合色狠狠天天综合色| 亚洲人成免费观看网站| 精品少妇人妻一区二区三区| 久久五月精品综网中文字幕| 午夜精品视频免费91| 色噜噜色一区二区三区| 免费黄片视频大全在线播放| 欧美日韩激情中文字幕| 91精品婷婷国产综合| av色剧情在线免费观看| 精品一区二区在线欧美日韩| 国产91人妻精品一区二区三区| 亚洲天堂毛片在线观看| 午夜在线免费观看小视频| 久久精品国产一区电影| 黄色成人av免费看| 国产精品久久中文字幕网| 日韩性生活视频免费播放| 国产成人+亚洲欧洲综合| 人妻少妇中文字幕在线播放| 午夜伦理视频免费观看| 国产精品一区二区av麻豆| 国产精品久久久久久久久| 日日躁夜夜躁狠狠躁黑人| 亚洲少妇精品视频在线|