shiro整合OAuth2學習體會
OAuth2是一個授權的協議,其使授權的流程變得更加簡單,本文是學習開濤部落格shiro整合OAuth2文章的個人學習體會,可以參考原博主的文章,http://jinnianshilongnian.iteye.com/blog/2038646,裡面有詳細的講解
服務端程式碼
1. 授權控制器
package com.github.zhangkaitao.shiro.chapter17.web.controller;
import java.net.URI;
import java.net.URISyntaxException;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse;
import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu .oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth 2.common.message.types.ResponseType;
import org.apache.oltu.oauth2.common.utils.OAuthUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import com.github.zhangkaitao.shiro.chapter17.Constants;
import com.github.zhangkaitao.shiro.chapter17.service.ClientService;
import com.github.zhangkaitao.shiro.chapter17.service.OAuthService;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-16
* <p>Version: 1.0
*/
@Controller
public class AuthorizeController {
@Autowired
private OAuthService oAuthService;
@Autowired
private ClientService clientService;
@RequestMapping("/authorize")
public Object authorize(Model model,HttpServletRequest request)
throws URISyntaxException, OAuthSystemException {
try {
//構建OAuth 授權請求
OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
//檢查傳入的客戶端id是否正確,通過查詢資料庫表oauth2_client比對。
if (!oAuthService.checkClientId(oauthRequest.getClientId())) {
OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
.setError(OAuthError.TokenResponse.INVALID_CLIENT)
.setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)
.buildJSONMessage();
return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
}
Subject subject = SecurityUtils.getSubject();
//如果使用者沒有登入,跳轉到服務端的登陸頁面
if(!subject.isAuthenticated()) {
if(!login(subject, request)) {//登入失敗時跳轉到服務端的登陸頁面
model.addAttribute("client", clientService.findByClientId(oauthRequest.getClientId()));//根據Id獲取客戶端實體資訊
return "oauth2login";
}
}
String username = (String)subject.getPrincipal();
//生成授權碼
String authorizationCode = null;
//responseType目前僅支援CODE,另外還有TOKEN
String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
if (responseType.equals(ResponseType.CODE.toString())) {
OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
authorizationCode = oauthIssuerImpl.authorizationCode();
oAuthService.addAuthCode(authorizationCode, username);//把授權碼儲存在cache中
}
//進行OAuth響應構建
OAuthASResponse.OAuthAuthorizationResponseBuilder builder =
OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);
//設定授權碼
builder.setCode(authorizationCode);
//得到到客戶端重定向地址
String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
//構建響應
final OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
//根據OAuthResponse返回ResponseEntity響應
HttpHeaders headers = new HttpHeaders();
headers.setLocation(new URI(response.getLocationUri()));
return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));
} catch (OAuthProblemException e) {
//出錯處理
String redirectUri = e.getRedirectUri();
if (OAuthUtils.isEmpty(redirectUri)) {
//告訴客戶端沒有傳入redirectUri直接報錯
return new ResponseEntity("OAuth callback url needs to be provided by client!!!", HttpStatus.NOT_FOUND);
}
//返回錯誤訊息(如?error=)
final OAuthResponse response =
OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND)
.error(e).location(redirectUri).buildQueryMessage();
HttpHeaders headers = new HttpHeaders();
headers.setLocation(new URI(response.getLocationUri()));
return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));
}
}
private boolean login(Subject subject, HttpServletRequest request) {
if("get".equalsIgnoreCase(request.getMethod())) {
return false;
}
String username = request.getParameter("username");
String password = request.getParameter("password");
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
return false;
}
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return true;
} catch (Exception e) {
request.setAttribute("error", "登入失敗:" + e.getClass().getName());
return false;
}
}
}
2. 訪問令牌控制器
package com.github.zhangkaitao.shiro.chapter17.web.controller;
import java.net.URISyntaxException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.github.zhangkaitao.shiro.chapter17.Constants;
import com.github.zhangkaitao.shiro.chapter17.service.OAuthService;
import com.github.zhangkaitao.shiro.chapter17.service.UserService;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-16
* <p>Version: 1.0
*/
@RestController
public class AccessTokenController {
@Autowired
private OAuthService oAuthService;
@Autowired
private UserService userService;
@RequestMapping("/accessToken")
public HttpEntity token(HttpServletRequest request)
throws URISyntaxException, OAuthSystemException {
try {
//構建OAuth請求
OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);
//檢查提交的客戶端id是否正確
if (!oAuthService.checkClientId(oauthRequest.getClientId())) {
OAuthResponse response =
OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
.setError(OAuthError.TokenResponse.INVALID_CLIENT)
.setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)
.buildJSONMessage();
return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
}
// 檢查客戶端安全KEY是否正確,查詢資料庫表oauth2_client,事先服務端資料庫就儲存了客戶端的訪問資訊。見表結構
if (!oAuthService.checkClientSecret(oauthRequest.getClientSecret())) {
OAuthResponse response =
OAuthASResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
.setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
.setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)
.buildJSONMessage();
return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
}
//獲取客戶端傳入的授權碼
String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE);
// 檢查驗證型別,此處只檢查AUTHORIZATION_CODE型別,其他的還有PASSWORD或REFRESH_TOKEN
if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())) {
if (!oAuthService.checkAuthCode(authCode)) {
OAuthResponse response = OAuthASResponse
.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
.setError(OAuthError.TokenResponse.INVALID_GRANT)
.setErrorDescription("錯誤的授權碼")
.buildJSONMessage();
return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
}
}
//生成Access Token
OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
final String accessToken = oauthIssuerImpl.accessToken();
//把access Token儲存在cache,這樣可以通過cache配置過期時間來使accessToken過期,
//當然也可以把accessToken儲存在資料庫,通過建立時間和當前時間區間判斷,方法多種
oAuthService.addAccessToken(accessToken, oAuthService.getUsernameByAuthCode(authCode));
//生成OAuth響應
OAuthResponse response = OAuthASResponse
.tokenResponse(HttpServletResponse.SC_OK)
.setAccessToken(accessToken)
.setExpiresIn(String.valueOf(oAuthService.getExpireIn()))
.buildJSONMessage();
//根據OAuthResponse生成ResponseEntity
return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
} catch (OAuthProblemException e) {
//構建錯誤響應
OAuthResponse res = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).error(e)
.buildJSONMessage();
return new ResponseEntity(res.getBody(), HttpStatus.valueOf(res.getResponseStatus()));
}
}
}
3. 資源控制器
package com.github.zhangkaitao.shiro.chapter17.web.controller;
import com.github.zhangkaitao.shiro.chapter17.Constants;
import com.github.zhangkaitao.shiro.chapter17.service.OAuthService;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.ParameterStyle;
import org.apache.oltu.oauth2.common.utils.OAuthUtils;
import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest;
import org.apache.oltu.oauth2.rs.response.OAuthRSResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-16
* <p>Version: 1.0
*/
@RestController
public class UserInfoController {
@Autowired
private OAuthService oAuthService;
@RequestMapping("/userInfo")
public HttpEntity userInfo(HttpServletRequest request) throws OAuthSystemException {
try {
//構建OAuth資源請求
OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);
//獲取Access Token
String accessToken = oauthRequest.getAccessToken();
//驗證Access Token
if (!oAuthService.checkAccessToken(accessToken)) {
// 如果不存在/過期了,返回未驗證錯誤,需重新驗證
OAuthResponse oauthResponse = OAuthRSResponse
.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
.setRealm(Constants.RESOURCE_SERVER_NAME)
.setError(OAuthError.ResourceResponse.INVALID_TOKEN)
.buildHeaderMessage();
HttpHeaders headers = new HttpHeaders();
headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));
return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED);
}
//返回使用者名稱,在cache裡獲取
String username = oAuthService.getUsernameByAccessToken(accessToken);
return new ResponseEntity(username, HttpStatus.OK);
} catch (OAuthProblemException e) {
//檢查是否設定了錯誤碼
String errorCode = e.getError();
if (OAuthUtils.isEmpty(errorCode)) {
OAuthResponse oauthResponse = OAuthRSResponse
.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
.setRealm(Constants.RESOURCE_SERVER_NAME)
.buildHeaderMessage();
HttpHeaders headers = new HttpHeaders();
headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));
return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED);
}
OAuthResponse oauthResponse = OAuthRSResponse
.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
.setRealm(Constants.RESOURCE_SERVER_NAME)
.setError(e.getError())
.setErrorDescription(e.getDescription())
.setErrorUri(e.getUri())
.buildHeaderMessage();
HttpHeaders headers = new HttpHeaders();
headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
}
客戶端程式碼
客戶端授權過程的攔截器
package com.github.zhangkaitao.shiro.chapter18.oauth2;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-18
* <p>Version: 1.0
*/
public class OAuth2AuthenticationFilter extends AuthenticatingFilter {
//oauth2 authc code引數名
private String authcCodeParam = "code";
//客戶端id
private String clientId;
//伺服器端登入成功/失敗後重定向到的客戶端地址
private String redirectUrl;
//oauth2伺服器響應型別
private String responseType = "code";
private String failureUrl;
public void setAuthcCodeParam(String authcCodeParam) {
this.authcCodeParam = authcCodeParam;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public void setResponseType(String responseType) {
this.responseType = responseType;
}
public void setFailureUrl(String failureUrl) {
this.failureUrl = failureUrl;
}
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String code = httpRequest.getParameter(authcCodeParam);
return new OAuth2Token(code);
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
return false;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
String error = request.getParameter("error");
String errorDescription = request.getParameter("error_description");
if(!StringUtils.isEmpty(error)) {//如果服務端返回了錯誤,也就是服務端裡檢查不通過進入if裡返回的錯誤
WebUtils.issueRedirect(request, response, failureUrl + "?error=" + error + "error_description=" + errorDescription);
return false;
}
Subject subject = getSubject(request, response);
if(!subject.isAuthenticated()) {
if(StringUtils.isEmpty(request.getParameter(authcCodeParam))) {
//如果使用者沒有身份驗證,且沒有auth code,則重定向到服務端授權,即訪問AuthorizeController的authorize方法
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
return executeLogin(request, response);
}
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
issueSuccessRedirect(request, response);
return false;
}
@Override
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException ae, ServletRequest request,
ServletResponse response) {
Subject subject = getSubject(request, response);
if (subject.isAuthenticated() || subject.isRemembered()) {
try {
issueSuccessRedirect(request, response);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
WebUtils.issueRedirect(request, response, failureUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
自定義認證
package com.github.zhangkaitao.shiro.chapter18.oauth2;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.URLConnectionClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthAccessTokenResponse;
import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-18
* <p>Version: 1.0
*/
public class OAuth2Realm extends AuthorizingRealm {
private String clientId;
private String clientSecret;
private String accessTokenUrl;
private String userInfoUrl;
private String redirectUrl;
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public void setAccessTokenUrl(String accessTokenUrl) {
this.accessTokenUrl = accessTokenUrl;
}
public void setUserInfoUrl(String userInfoUrl) {
this.userInfoUrl = userInfoUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof OAuth2Token;//表示此Realm只支援OAuth2Token型別
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
OAuth2Token oAuth2Token = (OAuth2Token) token;
String code = oAuth2Token.getAuthCode();
//下面這段程式碼是解決評論裡說的那個bug的一種方式。
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
if(code!=null){//第一次code不是null,放到session裡
session.setAttribute("code", code);
}else{//第二次 code是null,從session裡拿。
code=(String) session.getAttribute("code");
}
//上面是評論裡某人修復bug的一種方式
String username = extractUsername(code);
SimpleAuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(username, code, getName());
return authenticationInfo;
}
private String extractUsername(String code) {
try {
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthClientRequest accessTokenRequest = OAuthClientRequest
.tokenLocation(accessTokenUrl)
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId(clientId)
.setClientSecret(clientSecret)
.setCode(code)
.setRedirectURI(redirectUrl)
.buildQueryMessage();
OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);
String accessToken = oAuthResponse.getAccessToken();
Long expiresIn = oAuthResponse.getExpiresIn();
OAuthClientRequest userInfoRequest = new OAuthBearerClientRequest(userInfoUrl)
.setAccessToken(accessToken).buildQueryMessage();
OAuthResourceResponse resourceResponse = oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
String username = resourceResponse.getBody();
return username;
} catch (Exception e) {
e.printStackTrace();
throw new OAuth2AuthenticationException(e);
}
}
}
自定義token
package com.github.zhangkaitao.shiro.chapter18.oauth2;
import org.apache.shiro.authc.AuthenticationToken;
/**
* <p>User: Zhang Kaitao
* <p>Date: 14-2-18
* <p>Version: 1.0
*/
public class OAuth2Token implements AuthenticationToken {
public OAuth2Token(String authCode) {
this.authCode = authCode;
}
private String authCode;
private String principal;
public String getAuthCode() {
return authCode;
}
public void setAuthCode(String authCode) {
this.authCode = authCode;
}
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal;
}
public Object getCredentials() {
return authCode;
}
}
配置檔案
<!-- Realm實現 -->
<bean id="oAuth2Realm" class="com.github.zhangkaitao.shiro.chapter18.oauth2.OAuth2Realm">
<property name="cachingEnabled" value="true"/>
<
相關推薦
shiro整合OAuth2學習體會
OAuth2是一個授權的協議,其使授權的流程變得更加簡單,本文是學習開濤部落格shiro整合OAuth2文章的個人學習體會,可以參考原博主的文章,http://jinnianshilongnian.iteye.com/blog/2038646,裡面有詳細的講解
SpringBoot+shiro整合學習之登入認證和許可權控制
學習任務目標
使用者必須要登陸之後才能訪問定義連結,否則跳轉到登入頁面。
對連結進行許可權控制,只有噹噹前登入使用者有這個連結訪問許可權才可以訪問,否則跳轉到指定頁面。
輸入錯誤密碼使用者名稱或則使用者被設定為靜止登入,返回相應json串資訊
匯
Shiro學習--實際應用(SSM+Shiro)整合
可以參考Apache Shiro官網的文件:http://shiro.apache.org/reference.html
程式碼下載地址:https://download.csdn.net/download/qq_42969074/10810610
Apache Shiro是一個功能強大
shiro學習:shiro整合SpringMVC的web專案
這篇文章只是介紹了shiro與springweb專案進行的整合,並沒有涉及到認證的實現,如果您需要認證的相關實現,請看下我的下一篇:Shiro實現登入和退出
一、準備環境
與其它java開源框架類似,將shiro的jar包加入專案就可以使用shiro提供的功能了。shi
Python2.7 學習體會 @classmethod @staticmethod @property 之間的關系
bject 關系 rom sel def 實例 rop take 新的 先來一個實例場景,然後測試,比較,不懂的話到網上找資料:
#!/usr/bin/env python
#!/usr/bin/env python
class Date(object): def
Python2.7 學習體會 @classmethod @staticmethod @property 之間的關系二
普通 ear self static bject 代碼片段 split 本質 valid 先到百度找了一下資料,引用個重點,對比昨天實例來理解:引用:http://blog.csdn.net/carolzhang8406/article/details/6856817在Py
第六七章學習體會-----(第六次)
可用 nbsp 關註 授權 體會 發的 持續交付 第七章 變化 在這周我看了第六章敏捷流程跟第七章MSF。並有了以下學習總結。
敏捷這個詞聽起來就是反應靈敏迅速而有效,而在軟件按工程裏,敏捷不同於現有做法之處在於,敏捷的價值觀和流程是個人和交流、可用的軟件、與客戶合作、響應
學習體會
學習方法 java 天都 能力 平衡 學習c#已經有段時間了,當初在c#和java之間來回的平衡,最後選擇了c#。想想現在經歷的過程,走的彎路。不免有些笑自己,以前總覺得別人聰明,其實不然,因為別人的接受程度,學習方法,和別人交流,善於總結,勞逸結合程度,分析問題能力,平常的積累,還有
css學習體會之——塊級元素,行內元素長寬設置
寬高 lec 實戰 display 所有 splay 但是 isp 內聯元素 在做一些實戰的布局時,總會發現一些元素設置寬高有用,一些元素沒有用。下面來總結一下:
(1)塊級元素:所有的會級元素設置寬高都有效
(2)內聯元素:一般的內聯元素設置寬高沒有用,但是一些特殊的,如
信安軟考學習體會
軟考 2017年5月20日,我參加了信息安全工程師考試。考試結果還算可以,下面介紹一下學習感受。 一 參加了51cto的培訓。感覺老師的培訓視頻很好。特別是密碼學的朱老師,講課重點清晰。之前沒有接觸過密碼學,掌握了老師講的重點,考試的時候基本沒有超出強調的範圍。 二 我是為
Shiro整合Spring
static actor rate utf-8 -i pen aso not exp 首先需要添加shiro的spring整合包。
要想在WEB應用中整合Spring和Shiro的話,首先需要添加一個由spring代理的過濾器如下:
<!-- The filter-
python學習體會1
open -- 需要 python學習 相對路徑 pri read 執行命令 方法 今天 學習了如何引用模塊,主要有:sys.py os.py
在sys.py模塊中以下方法需要先熟悉一下:
import sys
print(sys.path) #打印環境變量
prin
20165302第一周學習體會
cnblogs 自己 image 開始 bin文件 截圖 src gpo ... 20165302第一周學習總結
用了三天多的時間做完了本次作業,其中有很多時間都花在了win10系統更新上面T_T,然而最後只用了Git bash....雖然中間遇到很多問題,但通過自己和同學
Spring Boot整合MyBatis學習總結
Spring Boot MyBatis druid數據源 druid sql監控 公司的很多項目都陸陸續續引入了Spring Boot,通過對Spring Boot的接觸了解發現其真的是大大地簡化了開發、簡化了依賴配置,很多功能註解一下就可以實現,真的是太方便了。下面記錄了一個Sp
【cocos2dx中Node類getParent和getChildByTag()】學習體會
mil 提高 cos cleanup HR -c ldr 12px 而不是
參考http://cn.cocos2d-x.org/doc/cocos2d-x-3.0/
業務邏輯:五、完成認證用戶的動態授權功能 六、完成Shiro整合Ehcache緩存權限數據
nbsp 數據 屬性 查詢 添加 系統 tro 系統管 核心
一、 完成認證用戶的動態授權功能
提示:根據當前認證用戶查詢數據庫,獲取其對應的權限,為其授權
操作步驟:
在realm的授權方法中通過使用principals對象獲取到當前登錄用戶
創建一個授權信息對象
教你 Shiro 整合 SpringBoot,避開各種坑
法則 從數據 協議 ret ppi 擁有 result 註入 nag
最近搞了下 Shiro 安全框架,找了一些網上的博客文章,但是一到自己實現的時候就遇到了各種坑,需要各種查資料看源碼以及各種測試。
那麽這篇文章就教大家如何將 Shiro 整合到 SpringBoot
spring與shiro整合
web.xml map life servle cti 我認 ref init for spring與shiro整合
(1)加入所需要是jar包
(2)配置shiro Filter(web.xml)
<!-- shiro過慮器,DelegatingFilte
springboot+shiro整合教程
sco actor attr run max 修改 authz prope ava
本教程整合環境: java8 maven
開發工具: idea
版本: springboot 1.5.15.RELEASE
註:
1.本教程數據操作是模擬數據庫操作,並沒有真正進行持
對二分法的學習體會以及關於結對編程的體驗分享
進一步 計算機 我們 思想 == article 利用 quick 函數 對二分法的學習體會以及關於結對編程的體驗分享
1) 二分搜索技術
二分搜索算法是運用分治策略的典型例子。二分搜索方法充分利用了元素間的次序關系,采用分治策略,可在最壞的情況下用O(logn)時間完成