Shiroフレームワーク
Apache Shiro は、認証、認可、暗号化、セッション管理を行う強力で使いやすい Java セキュリティフレームワークです。Shiroの分かりやすいAPIを使用することで、小規模なモバイルアプリケーションから大規模なWebアプリケーションやエンタープライズアプリケーションまで、あらゆるアプリケーションを迅速かつ容易に立ち上げて実行することができます!
Apache Shiroアーキテクチャ
SpringBoot認証を完了するためにShiroを統合します
shiroのコアの分析
MavenShiroを
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-spring</artifactId>
		<version>1.4.0</version>
	</dependency>
カスタムレルム
/**
 * カスタムレルム
 * 
 *
 */
public class UserRealm extends AuthorizingRealm{
	/**
	 * 認証ロジックを実行する
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("認証ロジックを実行する");
		//データベースのユーザー名とパスワードを想定する
		String name = "eric";
		String password = "123456";
		
		//ユーザー名とパスワードを決定するshiro判定ロジックを書く。
		//1.ユーザー名を決定する
		UsernamePasswordToken token = (UsernamePasswordToken)arg0;
		if(!token.getUsername().equals(name)){
			//ユーザー名が存在しない
			return null; //shiro要するに、UnKnowAccountExceptionがスローされる。
	 }
 // メソッドの前部は、実際にはPrincipalsであり、認証に成功した情報を格納する。
 return new SimpleAuthenticationInfo(user,password,getName());
}
	/**
	 * 認証ロジックを実行する
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("認証ロジックを実行する");
		return null;
	}
}
Shiro 設定クラスを記述します
/**
 * Shiro設定クラス
 * 
 *
 */
@Configuration
public class ShiroConfig {
	/**
	 * ShiroFilterFactoryBean を作成する。
	 */
	@Bean
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		
		//セキュリティマネージャを設定する
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		
		//shiroの組み込みフィルタを追加する
		/**
		 * Shiroパーミッション関連のインターセプターを実装するための組み込みフィルター
		 * よく使われるフィルター
		 * anon: アクセスに認証は必要ない
		 * authc: アクセスするには認証が必要である
		 * user: rememberMe関数を使用している場合は、直接アクセスできる。
		 * permsリソースにアクセスするには、リソースパーミッションが必要である。
		 * role: リソースにアクセスするためのロールパーミッションが必要である。
		 */
		Map<String,String> filterMap = new LinkedHashMap<String,String>();
		/*filterMap.put("/add", "authc");
		filterMap.put("/update", "authc");*/
		
		filterMap.put("/testThymeleaf", "anon");
		
		filterMap.put("/*", "authc");
		
		//調整されたログインページを修正する
		shiroFilterFactoryBean.setLoginUrl("/toLogin");
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
		
		
		return shiroFilterFactoryBean;
	}
	
	/**
	 * DefaultWebSecurityManagerを作成する。
	 */
	@Bean(name="securityManager")
	public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		//レルムを関連付ける
		securityManager.setRealm(userRealm);
		return securityManager;
	}
	
	/**
	 * レルムを作成する
	 */
	@Bean(name="userRealm")
	public UserRealm getRealm(){
		return new UserRealm();
	}
}
コントローラを記述します
/**
 * ログインロジックの処理
 */
	@RequestMapping("/login")
	public String login(String name,String password,Model model){
		
		/**
		 * shiroを使用して認証操作を記述する
		 */
		//1.サブジェクトを取得する
		Subject subject = SecurityUtils.getSubject();
		
		//2.ユーザーデータをカプセル化する
		UsernamePasswordToken token = new UsernamePasswordToken(name,password);
		
		//3.ログインメソッドを実行する
		try {
			subject.login(token);
			
			//ログインに成功する
			//テストに飛ぶ.html
			return "redirect:/testThymeleaf";
		} catch (UnknownAccountException e) {
			//e.printStackTrace();
			//ログイン失敗:ユーザー名が存在しない
			model.addAttribute("msg", "ユーザー名が存在しない");
			return "login";
		}catch (IncorrectCredentialsException e) {
			//e.printStackTrace();
			//ログイン失敗:パスワードエラー
			model.addAttribute("msg", "パスワードエラー");
			return "login";
		}
	}
SpringBoot認可を完了するためにShiroを統合します
reamlのauthorisationセクションを修正します
この部分の責任は、実際には、すでに認証されたユーザーに認可を与えることです。
認可には一般的に2つの方法があります。
- 最も直接的な一つは、直接ユーザーに関連する操作のアクセス許可を与える - shiroは、文字列を使用してアクセス許可を制御し、言い換えれば、アクセス許可を与えることは、このようなシステムなどの文字列を、ユーザーに与えることです:この文字列を表示し、ユーザーにこの文字列のタスクを与える認可のカスタム領域に与えられます。それに応じて、リソースに特定の system: view を必要とする文字列のアノテーションを設定します - shiro には関連するアノテーションがあります: @RequiresPermissions(), ユーザーがリソースにアクセスしたい場合、彼/彼女は対応する文字列を保持しなければなりません。 
- 2つ目は管理者の便宜のためで、ロールにパーミッションのセットが与えられ、ユーザーは特定のロールを保持している限り、対応するリソースにアクセスすることができます。 
以下はサンプルコードです:
public class UserRealm extends AuthorizingRealm {
 @Autowired
 private LoginService loginService;
 // 認証モジュール
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
 info.addStringPermission("system:view");
 info.addRole("admin");
 return info;
 }
 // 認証モジュール
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
 UsernamePasswordToken uptoken = (UsernamePasswordToken) authenticationToken;
 String username = uptoken.getUsername();
 String password = "";
 if(uptoken.getPassword() != null){
 password = new String(uptoken.getPassword());
 }
 int check = 0;
 try {
 check = loginService.check(username, password);
 } catch (UserNotExitingException e) {
 throw new UnknownAccountException(e.getMessage(),e);
 }catch (PasswordErrorException e){
 throw new IncorrectCredentialsException(e.getMessage(), e);
 }
 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(check,password,getName());
 return info;
 }
}
ShiroConfig を変更します
その他の構成securityManager、ShiroFilterFactoryBean、realmの構成はここでは省略し、次のコードを追加することに焦点を当てます -shiroは上記の2つのアノテーションの使用を完了するためにAOPアノテーションを使用するため、ここでは、アノテーションノーティファイアを構成するためにアノテーションノーティファイアを適切に動作させるために
/**
 * Shiro設定クラス
 * 
 *
 */
@Configuration
public class ShiroConfig {
 .......
	// 上記の内容は省略する
 /**
 * Shiroアノテーション通知器を有効にする
 */
 @Bean
 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
 @Qualifier("securityManager") SecurityManager securityManager)
 {
 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
 return authorizationAttributeSourceAdvisor;
 }
コントローラリソースを作成してアクセスを制限します。
@Controller
@RequestMapping("/back")
public class SystemController extends BaseController {
 @Autowired
 private MenuService menuService;
 
 @RequiresPermissions("system:view")
 @RequiresRoles("admin")
 @GetMapping("/index")
 public String getSystem(ModelMap modelMap){
 // ユーザー情報を取得する
 UserInfoBean user = getCurrentUser();
 // メニュー情報を取得する
 List<MenuVO> menus = menuService.getAllMenuForShow();
 modelMap.put("user",user);
 modelMap.put("menus", menus);
 return "back/index";
 }
}




