Spring Boot+Shro+JWTがマルチRealmを実現した時Filter異常捕捉
10248 ワード
最近、おじさんは会社の需要を受けて、前後の端の分離のバックグランドの管理モジュールのインターフェイスを構築します.登録モジュールに関する要求を簡単に説明する:ユーザがユーザ名とパスワードを入力してJWT Tokenトークン を取得する.ユーザは、JWT Tokenトークンを使用してバックエンドサービスインターフェース にアクセスする.
おじさんが簡単にSprigbootを集めてShroにする過程を言います.1.pom.xmlにShroを導入します.
テストコードを任意に書きます.
マルチRealmの登録が実現された後、JWT Realmのアイデンティティ検証エラーが発生した場合、JWT Filterで取得した異常タイプはAuthentication Exceptionであり、JWTRU Realmでは異なる異常に応じて処理ができなくなることが分かりました.どうすればいいですかトレース異常スローフローがマルチRealmを発見した場合、異常はModularRealm Authenticatorで処理され、Authentication Exceptionを一括してスローします.ですから、おじさんがModularRealm AuthenticatorのdoMultiRealmAuthenticationの書き換え方法を見つけたらいいです.
おじさんが簡単にSprigbootを集めてShroにする過程を言います.1.pom.xmlにShroを導入します.
org.apache.shiro
shiro-spring
2.自分のRealmを書く:UserRealm.java、JWTRRealm.java、/**
* UserRealm AuthenticatingRealm
**/
public class UserRealm extends AuthenticatingRealm {
/**
* Realm Realm
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
/**
*
**/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//TODO
}
}
/**
* JWTRealm , , AuthorizingRealm
**/
public class JWTRealm extends AuthorizingRealm {
/**
* Realm Realm
**/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
*
**/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//TODO
}
/**
* JWTToken
**/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
//TODO
}
}
3.JWT Filter.javaを書くpublic class JwtFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
//TODO
return true;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//TODO
return false;
}
}
4.ShroConfig.javaを書く/**
*
**/
@Configuration
public class ShiroConfig {
/**
* shiro Filter,
*/
@Bean
public FilterRegistrationBean filterRegistrationBean(DefaultWebSecurityManager securityManager)
throws Exception {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter((Filter) shiroFilter(securityManager).getObject());
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setAsyncSupported(true);
filterRegistration.setEnabled(true);
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
return filterRegistration;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// realm,
// One or more realms must be present to execute an authentication attempt. One
// or more realms must be present to execute an authentication attempt.
securityManager.setAuthenticator(authenticator());
securityManager.setAuthorizer(authorizer());
return securityManager;
}
/**
* realm
*/
@Bean("userRealm")
public Realm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
/**
* JWT token realm
*/
@Bean("jwtRealm")
public Realm jwtRealm() {
JWTRealm jwtRealm= new JWTRealm();
return jwtRealm;
}
/**
* Authenticator
*/
@Bean
public Authenticator authenticator() {
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();//
// Realm, ; jwt token
authenticator.setRealms(Arrays.asList(jwtRealm(), userRealm()));
// realm ,
authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
return authenticator;
}
/**
* authorizer
* @return
*/
@Bean
public Authorizer authorizer() {
ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();//
authorizer.setRealms(Arrays.asList(jwtShiroRealm()));
return authorizer;
}
/**
* session, 。 。
* , Subject.getSession() session, , noSessionCreation Filter
*/
@Bean
protected SessionStorageEvaluator sessionStorageEvaluator() {
DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
sessionStorageEvaluator.setSessionStorageEnabled(false);
return sessionStorageEvaluator;
}
/**
* , Filter
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
//
Map filterMap = new HashMap();
// JWT
filterMap.put("jwtFilter", jwtFilter());// JwTfilter
factoryBean.setFilters(filterMap);
//
factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap());
return factoryBean;
}
@Bean
protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/login", "noSessionCreation,anon"); // login ,noSessionCreation session
chainDefinition.addPathDefinition("/**", "noSessionCreation,jwtFilter"); //
return chainDefinition;
}
// @Bean , spring filter,
protected JwtFilter jwtFilter() {
return new JwtFilter();
}
/**
* Shiro
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
}
はい、ここに来たら、私達はシンロの集積作業を完成したと見なしてもいいです.テストコードを任意に書きます.
@RestController
public class TestController {
@GetMapping("/helloWorld")
@RequiresPermissions("system:test:hello")
public String helloWorld() {
return “hello world";
}
}
プロジェクトを起動して、このインターフェースをお願いします.マルチRealmの登録が実現された後、JWT Realmのアイデンティティ検証エラーが発生した場合、JWT Filterで取得した異常タイプはAuthentication Exceptionであり、JWTRU Realmでは異なる異常に応じて処理ができなくなることが分かりました.どうすればいいですかトレース異常スローフローがマルチRealmを発見した場合、異常はModularRealm Authenticatorで処理され、Authentication Exceptionを一括してスローします.ですから、おじさんがModularRealm AuthenticatorのdoMultiRealmAuthenticationの書き換え方法を見つけたらいいです.
public class MultiRealmAuthenticator extends ModularRealmAuthenticator {
private static final Logger log = LoggerFactory.getLogger(MultiRealmAuthenticator.class);
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection realms, AuthenticationToken token)
throws AuthenticationException {
AuthenticationStrategy strategy = getAuthenticationStrategy();
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
AuthenticationException authenticationException = null;
for (Realm realm : realms) {
aggregate = strategy.beforeAttempt(realm, token, aggregate);
if (realm.supports(token)) {
log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
} catch (AuthenticationException e) {
authenticationException = e;
if (log.isDebugEnabled()) {
String msg = "Realm [" + realm
+ "] threw an exception during a multi-realm authentication attempt:";
log.debug(msg, e);
}
}
aggregate = strategy.afterAttempt(realm, token, info, aggregate, authenticationException);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
if (authenticationException != null) {
throw authenticationException;
}
aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
}
書き換えた後、ShroConfig.javaの身分認証を置き換えればいいです. /**
* Authenticator
*/
@Bean
public Authenticator authenticator() {
MultiRealmAuthenticator authenticator = new MultiRealmAuthenticator();
// Realm, ; jwt token
authenticator.setRealms(Arrays.asList(jwtShiroRealm(), dbShiroRealm()));
// realm ,
authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
return authenticator;
}
穴が多くても、怖くない、起きても、穴に落ちるとおっさんが言いました.