は、私は自分のアプリケーションにはApache史郎を追加していると、次のエラーメッセージが本当に正確である場合、私は思ったんだけど:封印されていないSecurityManagerは実際にShiroの無効なアプリケーション構成ですか?
org.apache.shiro.UnavailableSecurityManagerException:いいえSecurityManagerを呼び出しコードにアクセス可能な、のいずれかに結合しorg.apache.shiro.util.ThreadContextまたはvm静的シングルトンとして宣言します。これは無効なアプリケーション構成です。私は、ソースコードを介してビットを見てきたし、私が得る印象がある限り、私は
SecurityUtils
を使用していないとということであり、私がそれを必要とするコンポーネントにSecurityManager
を渡すために喜んだ、私ドン
SecurityUtils
が使用するスタティックシングルトンに実際にSecurityManager
を割り当てる必要があります。
私が避けたいのは、シロはThreadLocal
に何かを入れているか、シロはそのThreadContext
サポートクラスを使用していることです。私はApache Thriftを使用しており、要求ごとに1スレッドのネットワーク設計に専念したくありません。城からの私の要求はかなり少ないので、私が下でやっていることを見せてくれるでしょう。
私は自分のアプリケーションでGuiceのを使用していますが、史郎AOPのものがThreadContext
に関連付けられているSubject
を持つに依存しているため、私はshiro-guice
を使用してないよ。代わりに、私は非常に簡単なGuiceモジュールから始めます。
public class ShiroIniModule extends AbstractModule {
@Override
protected void configure() {}
@Provides
@Singleton
public SecurityManager provideSecurityManager() {
return new DefaultSecurityManager(new IniRealm("classpath:shiro.ini"));
}
}
これは、本物のレルム/セキュリティマネージャの設定ではありませんが、テストするには十分です。次に、自分のアプリケーションのコンポーネントで使用される非常に限られたスコープを持つ独自のマネージャークラスを作成します。私はこれらの2つを持っています。 ThriftAuthenticationManager
およびThriftAuthorizationManager
である。ここでは前者は次のとおりです。
@Singleton
public class ThriftAuthenticationManager {
private final Logger log = LoggerFactory.getLogger(ThriftAuthenticationManager.class);
private final SecurityManager securityManager;
@Inject
public ThriftAuthenticationManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
public String authenticate(String username, String password) throws TException {
try {
Subject currentUser = new Subject.Builder(securityManager).buildSubject();
if (!currentUser.isAuthenticated()) {
currentUser.login(new UsernamePasswordToken(username, password));
}
String authToken = currentUser.getSession().getId().toString();
Preconditions.checkState(!Strings.isNullOrEmpty(authToken));
return authToken;
}
catch (AuthenticationException e) {
throw Exceptions.security(SecurityExceptions.AUTHENTICATION_EXCEPTION);
}
catch(Throwable t) {
log.error("Unexpected error during authentication.", t);
throw new TException("Unexpected error during authentication.", t);
}
}
}
、後者:
@Singleton
public class ThriftAuthorizationManager {
private final Logger log = LoggerFactory.getLogger(ThriftAuthorizationManager.class);
private final SecurityManager securityManager;
@Inject
public ThriftAuthorizationManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
public void checkPermissions(final String authToken, final String permissions)
throws TException {
withThriftExceptions(new Callable<Void>() {
@Override
public Void call() throws Exception {
securityManager.checkPermission(getPrincipals(authToken), permissions);
return null;
}
});
}
public void checkPermission(final String authToken, final Permission permission)
throws TException {
withThriftExceptions(new Callable<Void>() {
@Override
public Void call() throws Exception {
securityManager.checkPermission(getPrincipals(authToken), permission);
return null;
}
});
}
private Subject getSubject(String authToken) {
return new Subject.Builder(securityManager).sessionId(authToken).buildSubject();
}
private PrincipalCollection getPrincipals(String authToken) {
return getSubject(authToken).getPrincipals();
}
private void withThriftExceptions(Callable<Void> callable) throws TException {
try {
callable.call();
}
catch(SessionException e) {
throw Exceptions.security(SecurityExceptions.SESSION_EXCEPTION);
}
catch(UnauthenticatedException e) {
throw Exceptions.security(SecurityExceptions.UNAUTHENTICATED_EXCEPTION);
}
catch(AuthorizationException e) {
throw Exceptions.security(SecurityExceptions.AUTHORIZATION_EXCEPTION);
}
catch(ShiroException e) {
throw Exceptions.security(SecurityExceptions.SECURITY_EXCEPTION);
}
catch(Throwable t) {
log.error("An unexpected error occurred during authorization.", t);
throw new TException("Unexpected error during authorization.", t);
}
}
}
マイスリフトサービスは、認証と承認のために上記の2つのクラスを使用します。例:
@Singleton
public class EchoServiceImpl implements EchoService.Iface {
private final Logger log = LoggerFactory.getLogger(EchoServiceImpl.class);
private final ThriftAuthorizationManager authorizor;
@Inject
public EchoServiceImpl(ThriftAuthorizationManager authorizor) {
this.authorizor = authorizor;
}
@Override
public Echo echo(String authToken, Echo echo) throws TException {
authorizor.checkPermissions(authToken, "echo");
return echo;
}
}
だから、私は実際にいくつかの欲求を持っていると思います。
引用したエラーは実際にはエラーですか、過度のログメッセージですか?
ShiroUtils
を絶対に使用しないと、シロは、ThreadContext
にあるものに頼っているのではないですか?1スレッドあたりのリクエスト環境を保証できない場合は、
SecurityUtils#setSecurityManager
を使用することに何らかの害がありますか?私はShiroの高度なアクセス許可(
org.apache.shiro.authz.Permission
)をまだ試していません。彼らはThreadContext
の中の何かに頼っているのですか、私は後で早く調べなければならない奇妙なことをしていますか?問題が発生する可能性がありますか、何か改善する可能性がありますか?