最近、同社のサービスは、このような要望を持っている:要求し、それは権限ゲートウェイ層の傍受を開始する時期のバックオフィスサービスの二組は、バックグラウンドです。現在切片へのユーザー、役割、およびURLアドレス要求ログインが所有しているメニューによると、別のサービス・アドレスに要求することができます。史郎権管理に使用ゲートウェイ層は、優れたパッケージの役割、権限と口座番号を持っています。しかし、URIの傍受の問題を理解するために考えられてきました。史郎は、当社の既存のログインルックスからソースコードを参照してください。最後に解決策を見つけることができました
ログイン時史郎は、ログイン方法は、対象の使用です。
被験者currentLoginUser = SecurityUtils.getSubject()。
// A:是否已经登录
IF(currentLoginUser.isAuthenticated()){
ブールisAjax =(ブール)request.getAttribute( "X_IS_AJAX")。
(isAjax){もし
リターンAjaxResponse.success(NULL)。
}他{
response.sendRedirect(homepageUrl)。
ヌルを返します。
}
}
// B:查询用户信息
CarAdmUserユーザー= carAdmUserExMapper.queryByAccount(ユーザ名、NULL);
IF(ユーザ== NULL){
リターンAjaxResponse.fail(RestErrorCode.USER_NOT_EXIST)。
}
// C:密码不正确
ストリングenc_pwd = PasswordUtil.md5(パスワード、user.getAccount())。
(もし!enc_pwd.equalsIgnoreCase(user.getPassword())){
AjaxResponse.failリターン(RestErrorCode.USER_PASSWORD_WRONG);
}
// E:ユーザ状態
IF(!user.getStatus()= NULL && user.getStatus()intValue()== 100){
リターンAjaxResponse.fail(RestErrorCode.USER_INVALID );
}
// F:ログインを行う
{試し
//ログイン史郎
UsernamePasswordToken新しい新しいトークン= UsernamePasswordToken(ユーザ名、password.toCharArray()); )currentLoginUser.login(トークン;
//サポートするすべてのユーザーのログインセッションIDを記録します"自動セッション・クリーンアップのシステム管理「機能
文字列セッションID =(文字列)currentLoginUser.getSession()のgetId();.
redisSessionDAO.saveSessionIdOfLoginUser(ユーザ名、セッションID);
redisTemplate.delete(redis_login_key);
redisTemplate.delete(redis_getmsgcode_key)。
}キャッチ(含むAuthenticationException AEX){
リターンAjaxResponse.fail(RestErrorCode.USER_LOGIN_FAILED)。
}
//返回登录成功
ブールisAjax =(ブール)request.getAttribute( "X_IS_AJAX")。
(isAjax){もし
リターンAjaxResponse.success(NULL)。
}他{
response.sendRedirect(homepageUrl)。
ヌルを返します。
}
currentLoginUser.login(トークン);しろ)は(AuthorizingRealm内部に書き換えられます
パッケージcom.sq.transportmanage.gateway.service.shiro.realm。 輸入com.sq.transportmanage.gateway.dao.entity.driverspark.CarAdmUser; 輸入com.sq.transportmanage.gateway.dao.mapper.driverspark.ex.SaasPermissionExMapper; 輸入com.sq.transportmanage.gateway.dao.mapper.driverspark.ex.SaasRoleExMapper; 輸入com.sq.transportmanage.gateway.service.auth.MyDataSourceService。 輸入org.apache.shiro.authc *。; 輸入org.apache.shiro.authz.AuthorizationInfo; 輸入org.apache.shiro.authz.SimpleAuthorizationInfo; 輸入org.apache.shiro.realm.AuthorizingRealm; 輸入org.apache.shiro.subject.PrincipalCollection。 輸入org.slf4j.Logger; 輸入org.slf4j.LoggerFactory。 輸入org.springframework.beans.factory.annotation.Autowired; org.springframework.stereotype.Componentインポート、 インポートはjava.util.HashSet; インポートはjava.util.List; インポートjava.util.Set; / **認証及び権利** / / ** *これは、史郎SSOLoginユーザー獲得ですコンフィギュレーション属性 * / @Component パブリッククラスUsernamePasswordRealm AuthorizingRealm {延び プライベート静的ロガーロガー=最終LoggerFactory.getLogger(UsernamePasswordRealm.class); @Autowired プライベートmyDataSourceService myDataSourceService; @Autowired プライベートsaasPermissionExMapper saasPermissionExMapper; @Autowired プライベートsaasRoleExMapper saasRoleExMapper; / **重量書き込み:取得ユーザ認証情報** / @Override AuthenticationInfo doGetAuthenticationInfoは(AuthenticationToken AuthenticationToken)を保護含むAuthenticationException {からスロー logger.info( "[取得したユーザ認証情報スタート] AuthenticationToken =" + AuthenticationToken); 試み{ UsernamePasswordTokenトークン=(UsernamePasswordToken)AuthenticationToken; CarAdmUser必ずadmuser = myDataSourceService.queryByAccount(トークン。 getUsername()); SSOLoginUser loginUser =新新SSOLoginUser(); //ユーザーが現在ログインし loginUser.setId(adMUser.getUserIdを()); //ユーザーID loginUser.setLoginName(adMUser.getAccount()); //ログイン loginUser .setMobile(adMUser.getPhone()); //電話番号 loginUser.setType(NULL); // loginUser.setName(adMUser.getUserName()); //実際の名前 loginUser.setEmail(adMUser.getEmail()); //メールアドレス loginUser.setStatus(adMUser.getStatus()); //状態 loginUser.setAccountType(adMUser.getAccountType()); //独自のアカウントの種類:[100通常のユーザー]、[900アドミニストレータ] loginUser.setLevel(adMUser.getLevel()); loginUser.setUuid(adMUser.getUuid()); リストの<string> menuUrlList = saasPermissionExMapper.queryPermissionCodesOfUser(adMUser.getUserId()); loginUser。 setMenuUrlList(menuUrlList); // ------------------------------------------- --------------------------------------------------データ許可------------ BEGIN logger.info( "= [ユーザ認証情報が取得された" + loginUserを); 戻り新しい新しいSimpleAuthenticationInfo(loginUser、authenticationToken.getCredentials()、this.getName( )); }キャッチ(例外e){ logger.error( "获取用户的身份认证信息异常"、E)。 ヌルを返します。 } } @Override AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){保護 SSOLoginUser loginUser =(SSOLoginUser)principalCollection.getPrimaryPrincipalは(); 文字列のアカウント= loginUser.getLoginName(); //登录名 一覧<文字列> perms_string = saasPermissionExMapper.queryPermissionCodesOfUser(loginUser.getId()); 一覧<文字列> roles_string = saasRoleExMapper.queryRoleCodesOfUser(loginUser.getId()); SimpleAuthorizationInfo authorizationInfo =新しいSimpleAuthorizationInfo(); セット<文字列>の役割=新しいHashSetの<文字列>(roles_string)。 authorizationInfo。 logger.info( "[获取用户授权信息(角色)] "+アカウント+"=" +役割)。 セット<文字列>パーマ=新しいHashSetの<文字列>(perms_string)。 authorizationInfo。 logger.info( "[获取用户授权信息(权限)] "+アカウント+"=" +パーマ)。 authorizationInfoを返します。 } @Override パブリックオブジェクトgetAuthorizationCacheKey(PrincipalCollectionプリンシパル){ SSOLoginUser loginUser =(SSOLoginUser)principals.getPrimaryPrincipal(); 文字列のアカウント= loginUser.getLoginName(); //登录名 の戻り"-AuthInfo - " +アカウント。 } @Override 公共ボイドclearCachedAuthorizationInfo(PrincipalCollectionプリンシパル){ super.clearCachedAuthorizationInfo(プリンシパル)。 } @Override 公共ボイドclearCachedAuthenticationInfo(PrincipalCollectionプリンシパル){ super.clearCachedAuthenticationInfo(プリンシパル)。 } @Override 公共ボイドclearCache(PrincipalCollectionプリンシパル){ super.clearCache(プリンシパル)。 } }
これは、次のメニューは、特定の権限で、史郎の内部へのログイン情報を介して行うことができます。通常、コメント史郎を使用
@RequiresPermissions(値= { "値" })
正常に使用することができます。決定することによって、AOP方法で使用される@RequiresPermissions源か権限があるか否かを判断する設定値の値(参照:https://blog.csdn.net/xiewenfeng520/article/details/89447749)
。しかし、私たちのプロジェクトは、当局がゲートウェイを設定して、指定したURLにジャンプするかどうかを判断するためにやっている、これはゲートウェイ層であり、多少異なります。私は、URLアドレス内の私のテーブル関係のパラメータが渡されないので、URLを傍受するためにどのように良い一日と思っています。そして、史郎を達成するためのソースコードを読んだ後、
私は自分自身が問題を考えていない見つけましたが、URLが渡されます。:この変更計画はそう
インターセプトURLアドレスへの迎撃書き込み)1を
ログインすると、メニューが内側史郎を置くためにユーザーの許可が含まれます)2を
、管理者が直接通じ場合、判断内部インターセプタ)3を、そうでない場合はユーザーが権限を持っているかどうかを確認します。
特定の実装コード:
1)Zuulブロッカー:
パッケージcom.sq.transportmanage.gateway.api.web.filter。 輸入com.alibaba.fastjson.JSONObject; 輸入com.netflix.zuul.ZuulFilter; 輸入com.netflix.zuul.context.RequestContext; 輸入com.sq.transportmanage.gateway.api.common.AuthEnum; 輸入com.sq.transportmanage.gateway.service.shiro.realm.SSOLoginUser; 輸入com.sq.transportmanage.gateway.service.shiro.session.WebSessionUtil; 輸入org.apache.shiro.authz.annotation.RequiresPermissions。 輸入org.slf4j.Logger; 輸入org.slf4j.LoggerFactory。 輸入org.springframework.stereotype.Component; インポートのjavax.servlet.http.HttpServletRequest; 輸入はjava.util.List; / ** * @program:SQ-組合管理 * @description:AccessFilter * @author:ZJW * @Create:2020年2月23日夜06時57 ** / @Component @RequiresPermissions( "/") パブリッククラスAccessFilterはZuulFilter {延び プライベート静的ロガーロガー= LoggerFactory.getLogger(AccessFilter.class)を、 @Override パブリック文字列のfilterType(){ 戻り「プレ」。 } @Override 公共INT filterOrder(){ 1を返します。 } @Override パブリックブールshouldFilter(){ trueを返します。 } @Override パブリックオブジェクトラン(){ RequestContextのCTX = RequestContext.getCurrentContext()。 文字列URI = request.getRequestURI()のtoString()。 HttpServletRequestのリクエスト= ctx.getRequest()。 logger.info(String.Formatの( "%sの%sの要求"、request.getMethod()、request.getRequestURL()のtoString())); SSOLoginUser loginUser = WebSessionUtil.getCurrentLoginUser()。 logger.info(String.Formatの( "%sのloginUser%s"は、loginUser.getLoginName()、loginUser.getName()))。 / **用户是否有权限** / ブールBL =偽; //如果是管理员直接通过 IF(AuthEnum.MANAGE.getAuthId()に等しい(loginUser.getAccountType())){ BL = TRUE。 }他{ リストの<string>メニューURL = loginUser.getMenuUrlList()。 IF(menuUrl.contains(URI)){ BL = TRUE。 } } IF(BL){ ctx.addZuulRequestHeader( "user_token"、JSONObject.toJSONString(loginUser)); }他{ ctx.setSendZuulResponse (偽); //要求をフィルタリング、それをルーティングせず ctx.setResponseStatusCode(401); //戻りエラーコード ctx.setResponseBody( "{\"コード\ ":0、\" \結果":\" 認証ゲートウェイ!失敗した認証モードが2である\ "}"); //は、エラー内容を返す ctx.set( "isSuccess"、偽の); } // TODOここに増加する権利判断 戻りCTXを; } }
2)史郎ストレージ権:
パッケージcom.sq.transportmanage.gateway.service.shiro.realm。 輸入com.sq.transportmanage.gateway.dao.entity.driverspark.CarAdmUser; 輸入com.sq.transportmanage.gateway.dao.mapper.driverspark.ex.SaasPermissionExMapper; 輸入com.sq.transportmanage.gateway.dao.mapper.driverspark.ex.SaasRoleExMapper; 輸入com.sq.transportmanage.gateway.service.auth.MyDataSourceService。 org.apache.shiro.authcインポートします。* ; 輸入org.apache.shiro.authz.AuthorizationInfo; 輸入org.apache.shiro.authz.SimpleAuthorizationInfo; 輸入org.apache.shiro.realm.AuthorizingRealm; 輸入org.apache.shiro.subject.PrincipalCollection。 輸入org.slf4j.Logger; 輸入org.slf4j.LoggerFactory。 org.springframework.beans.factory.annotation.Autowiredインポート、 インポートorg.springframework.stereotype.Component; インポートはjava.util.HashSet; インポートはjava.util.List; インポートjava.util.Set; / * * *認証と権限* / / * * *この得られたシロのSSOLoginユーザ設定属性 * / @Component パブリック クラスAuthorizingRealm {延びUsernamePasswordRealm プライベート 静的最終ロガーロガー= LoggerFactory.getLogger(UsernamePasswordRealm。クラス); @Autowired プライベートmyDataSourceService myDataSourceServiceと、 @Autowired プライベートSaasPermissionExMapper SaasPermissionExMapper; @Autowired プライベートSaasRoleExMapper saasRoleExMapper; / * *書き換え:取得ユーザ認証情報* * / @Overrideは 保護AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken AuthenticationToken)を含むAuthenticationException {からスロー logger.info(「[取得したユーザ認証情報スタート] = AuthenticationToken " + AuthenticationToken); 試み{ UsernamePasswordTokenトークン = (UsernamePasswordToken)AuthenticationToken; CarAdmUser必ずadmuser =新しい新 myDataSourceService.queryByAccount(token.getUsername())。 LoginUser SSOLoginUser = SSOLoginUser(); // 現在ログオンしているユーザー loginUser.setId(adMUser.getUserId()); // ユーザID loginUser.setLoginName(adMUser.getAccount()); // ログイン loginUser.setMobile(adMUser.getPhone ()); // 電話番号 loginUser.setName(adMUser.getUserName()); // 本名 loginUser.setEmail(adMUser.getEmail()); // メールアドレス loginUser.setType(ヌル); // loginUser.setStatus (adMUser.getStatus()); //状態 loginUser.setAccountType(adMUser.getAccountType()); // 独自のアカウントの種類:[100の普通のユーザー]、[900管理者] loginUser.setLevel(adMUser.getLevel()); loginUser.setUuid(adMUser.getUuid( )); リストの<string> menuUrlList = saasPermissionExMapper.queryPermissionCodesOfUser(adMUser.getUserId()); loginUser.setMenuUrlList(menuUrlList); // --------------------- -------------------------------------------------- ----------------------------------データ許可はBEGIN (logger.info 「[ユーザ認証情報を取得します] = " + loginUser); リターン 新しい新SimpleAuthenticationInfo(loginUser、authenticationToken.getCredentials()、 この.getName()); } キャッチ(例外E){ logger.error(" 異常取得したユーザ認証情報" 、E); 戻り NULL ; } } @Overrideは 保護AuthorizationInfoをdoGetAuthorizationInfo(principalCollection principalCollection){ SSOLoginUser loginUser = (SSOLoginUser)principalCollection.getPrimaryPrincipal(); 文字列アカウント = loginUser.getLoginName(); // ログイン 一覧<ストリング> perms_string = saasPermissionExMapper.queryPermissionCodesOfUser(loginUser.getId())。 一覧 <文字列> roles_string = saasRoleExMapper.queryRoleCodesOfUser(loginUser.getId()); SimpleAuthorizationInfo authorizationInfo = 新しいSimpleAuthorizationInfo(); セット <文字列>の役割= 新しい HashSetの<文字列> (roles_string)。 authorizationInfo.setRoles(ロール); logger.info(" [获取用户授权信息(角色)] " +アカウント+ " = " + 役割)。 セット <文字列>パーマ= 新しいですHashSetの<ストリング> (perms_string)。 authorizationInfo.setStringPermissions(パーマ)。 logger.info(" [获取用户授权信息(权限)] " +アカウント+ " = " + パーマ)。 返すauthorizationInfoを。 } @Override パブリックオブジェクトgetAuthorizationCacheKey(PrincipalCollectionプリンシパル){ SSOLoginUser loginUser = (SSOLoginUser)principals.getPrimaryPrincipal(); 文字列のアカウント = loginUser.getLoginName(); // 登录名 の戻り " -AuthInfo- " + アカウント。 } @Override 公共 ボイドclearCachedAuthorizationInfo(PrincipalCollectionプリンシパル){ super.clearCachedAuthorizationInfo(プリンシパル)。 } @Override 公共 ボイドclearCachedAuthenticationInfo(PrincipalCollectionプリンシパル){ super.clearCachedAuthenticationInfo(プリンシパル)。 } @Override 公共 ボイドclearCache(PrincipalCollectionプリンシパル){ super.clearCache(プリンシパル)。 } }
おそらくアイデアはこれです。。。