shiro簡易Javaセキュリティフレームワーク
52270 ワード
この2,3日はプロジェクトでシロというフレームワークが使われていたので、休みの間にシロをしっかり補習していました.
一、シロって何?
shiroは強力なJavaセキュリティフレームワークであり、認証を実行します.ライセンス、パスワード、セッション管理.shiroを使用するとAPIが分かりやすく、どのアプリケーションにも簡単に統合できます.
ここでも説明します:Spring Securityというセキュリティフレームワークについては、両者は機能的に非常に似ているので、一つを勉強した後、最後にもう一つを勉強したほうがいいです.
二、shiroの三大コアコンポーネント
1、subject:現在の操作ユーザーを表すと簡単に理解できます.実はその深層表現の意味は第三者のプロセスです.これは、現在のシステムとインタラクティブな「もの」を意味します.ここでは、私たちのシステムを直接操作しているので、一般的には、subjectは現在のユーザーであり、subjectを通じてログイン認証が必要なユーザー名パスワードが安全な操作データに関連していることを簡単に取得することができます.
2、securityManager:shiroフレームワークの核心であり、典型的なFacadeモードであり、shiroはSecurityManagerによって内部コンポーネントインスタンスを管理し、それによって安全管理の各種サービスを提供する.
3、Realm:Realmはshiroフレームワークとアプリケーションセキュリティデータとの架け橋またはコネクタであり、ユーザーが認証/認可を登録する必要がある場合、shiroはアプリケーション構成のRealmからユーザーとその権限情報を検索する.
ここで注意すべきことは、shiroを構成する際に、少なくとも1つのRealmを指定する必要があります.ユーザー認証または認可は、複数のRealmを構成することができます.
三、SpringBoot集積Shiro
プロジェクトでは、shiroコンフィギュレーションクラスを構成するのが一般的です.このクラスでは、shiroで非常に重要な認証、アクセス制御情報、およびRealmの管理を構成します.
私が書いたshiroConfigの例を書いてみます.参考にしてください.
簡単なログインURL、ログイン成功URL、nopermission権限のないURLが配置されています.そしてMyRealmオブジェクトはspringによって管理されます.後ろにブロック機能に似た/admin/**があります....認証が必要なのか、認証が必要なのか、対応する役割、権限などが必要なのか.
MyRealm:
その最も基本的なRealmクラスが作成され、1、doGetAuthenticationInfo shiroがユーザー認証時に自動的にこのメソッドを呼び出す2つの方法が表示されます.この方法のパラメータは,実際には簡易なユーザアイデンティティトークンを用いていることがわかる.このユーザは当然認証が必要なユーザであり,トークンから現在の認証ユーザのユーザ名とログインパスワードを取り出すことができる.自然の後ろにはMD 5などのパスワード暗号化があります.ユーザのアイデンティティを最終的に判断するには、何回の塩添加反復が必要であるか.
2.doGetAuthorizationInfoが許可したコールバック方法.この方法には、現在のユーザーに権限を与える操作が含まれていることがわかります.
あちらはみんなのテストを便利にしてcontrollerを書きました.
login.htmlログインページ
noPermission.html権限ページなし
success.htmlログイン成功ページ
このような最も簡単なshiroプロジェクトは構築に成功したが、開発中にshiroフレームワークはこのように使用されないと言いたい.特に、特定のURLに特定のロールと権限が必要な場合、プロファイルに大量に構成され、プロジェクトのメンテナンスコストが増加します.後期URLアドレスは特に多く、私たちのshiroConfigという構成クラスは非常に膨大になる可能性があります.そこで次の一枚はshiroの注釈ベースの開発とよくあるshiroラベル(shiro統合thymeleafの使い方)についてお話ししたいと思います.
–未完待機
OK、週末は楽しかった~
一、シロって何?
shiroは強力なJavaセキュリティフレームワークであり、認証を実行します.ライセンス、パスワード、セッション管理.shiroを使用するとAPIが分かりやすく、どのアプリケーションにも簡単に統合できます.
ここでも説明します:Spring Securityというセキュリティフレームワークについては、両者は機能的に非常に似ているので、一つを勉強した後、最後にもう一つを勉強したほうがいいです.
二、shiroの三大コアコンポーネント
1、subject:現在の操作ユーザーを表すと簡単に理解できます.実はその深層表現の意味は第三者のプロセスです.これは、現在のシステムとインタラクティブな「もの」を意味します.ここでは、私たちのシステムを直接操作しているので、一般的には、subjectは現在のユーザーであり、subjectを通じてログイン認証が必要なユーザー名パスワードが安全な操作データに関連していることを簡単に取得することができます.
2、securityManager:shiroフレームワークの核心であり、典型的なFacadeモードであり、shiroはSecurityManagerによって内部コンポーネントインスタンスを管理し、それによって安全管理の各種サービスを提供する.
3、Realm:Realmはshiroフレームワークとアプリケーションセキュリティデータとの架け橋またはコネクタであり、ユーザーが認証/認可を登録する必要がある場合、shiroはアプリケーション構成のRealmからユーザーとその権限情報を検索する.
ここで注意すべきことは、shiroを構成する際に、少なくとも1つのRealmを指定する必要があります.ユーザー認証または認可は、複数のRealmを構成することができます.
三、SpringBoot集積Shiro
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
プロジェクトでは、shiroコンフィギュレーションクラスを構成するのが一般的です.このクラスでは、shiroで非常に重要な認証、アクセス制御情報、およびRealmの管理を構成します.
私が書いたshiroConfigの例を書いてみます.参考にしてください.
/**
* 2020/05/20
*/
@Configuration
public class ShiroConfig {
// Shiro
@Bean
public SecurityManager securityManager(Realm myRealm){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
// Realm, Realm
securityManager.setRealm(myRealm);
return securityManager;
}
// Realm bean, bean
@Bean
public Realm myRealm(){
MyRealm realm=new MyRealm();
return realm;
}
// Shiro bean, bean Shiro
//
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
// Shiro ,
ShiroFilterFactoryBean shiroFilter=new ShiroFilterFactoryBean();
// Shiro , Realm
shiroFilter.setSecurityManager(securityManager);
// , html jsp ,
// Shiro , Shiro
//
shiroFilter.setLoginUrl("/");
// , Shiro , Shiro
shiroFilter.setSuccessUrl("/success");
// , Shiro , Shiro
// ,
shiroFilter.setUnauthorizedUrl("/noPermission");
// Map , Map , Shiro
Map<String,String> map=new LinkedHashMap<String,String>();
// /login anon ( )
map.put("/login","anon");
//
// Shiro
// /admin/** , admin
// authc ( ), ( )
// : **
// *
// ?
map.put("/admin/**","authc");
map.put("/user/**","authc");
// , Map ,
// /** Shiro
// map.put("/**","authc");
shiroFilter.setFilterChainDefinitionMap(map);
return shiroFilter;
}
}
簡単なログインURL、ログイン成功URL、nopermission権限のないURLが配置されています.そしてMyRealmオブジェクトはspringによって管理されます.後ろにブロック機能に似た/admin/**があります....認証が必要なのか、認証が必要なのか、対応する役割、権限などが必要なのか.
MyRealm:
/**
* 2020/05/20
*/
public class MyRealm extends AuthorizingRealm {
/**
* , Shiro
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username=token.getUsername();//
String password=new String(token.getPassword());//
System.out.println(username+" ----- "+password);
/**
* , ,
* if
*/
if(!"admin".equals(username)&&!"zhangsan".equals(username)&&!"user".equals(username)){
throw new UnknownAccountException();//
}
/**
* , ,
* IP ,
*/
if("zhangsan".equals(username)){
throw new LockedAccountException();//
}
/**
* ,
* :
* , ,
*
*/
//
// HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
// credentialsMatcher.setHashAlgorithmName("MD5");
// credentialsMatcher.setHashIterations(2);
//
// this.setCredentialsMatcher(credentialsMatcher);
//
// Object obj = new SimpleHash("MD5","123456","",1);
return new SimpleAuthenticationInfo(username,"e10adc3949ba59abbe56e057f20f883e",getName());
}
/**
* ,
* , shiro
* : ,Shiro ,
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// ,
Object obj = principalCollection.getPrimaryPrincipal();
// set
Set<String> roles = new HashSet<>();
if("admin".equals(obj)){
System.out.println(" --- admin --------");
roles.add("admin");
roles.add("user");
}
if("user".equals(obj)){
System.out.println(" --- user --------" + obj);
roles.add("user");
}
Set<String> permissions = new HashSet<>();
if("admin".equals(obj)){
// admin:add admin add
permissions.add("admin:add");
}
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
}
その最も基本的なRealmクラスが作成され、1、doGetAuthenticationInfo shiroがユーザー認証時に自動的にこのメソッドを呼び出す2つの方法が表示されます.この方法のパラメータは,実際には簡易なユーザアイデンティティトークンを用いていることがわかる.このユーザは当然認証が必要なユーザであり,トークンから現在の認証ユーザのユーザ名とログインパスワードを取り出すことができる.自然の後ろにはMD 5などのパスワード暗号化があります.ユーザのアイデンティティを最終的に判断するには、何回の塩添加反復が必要であるか.
2.doGetAuthorizationInfoが許可したコールバック方法.この方法には、現在のユーザーに権限を与える操作が含まれていることがわかります.
あちらはみんなのテストを便利にしてcontrollerを書きました.
/**
* 2020/05/20
*/
@Controller
public class TestController {
@RequestMapping("/")
public String index(){
return "login";
}
@RequestMapping("/login")
public String login(String username, String password, Model model){
// ,
Subject subject= SecurityUtils.getSubject();
// , , , Shiro
// :
subject.logout();
// ( ), if
if(!subject.isAuthenticated()){
// ,
UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
try {
/**
* , Realm
*
*/
subject.login(usernamePasswordToken);
} catch (UnknownAccountException e) {
// e.printStackTrace();
model.addAttribute("errorMessage"," !");
return "login";
}catch (LockedAccountException e) {
// e.printStackTrace();
model.addAttribute("errorMessage"," !");
return "login";
}catch (IncorrectCredentialsException e) {
// e.printStackTrace();
model.addAttribute("errorMessage"," ");
return "login";
}catch (AuthenticationException e) {
e.printStackTrace();
model.addAttribute("errorMessage"," !");
return "login";
}
}
return "redirect:/success";
}
@RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
// shiro ,
subject.logout();
return "redirect:/";
}
@RequestMapping("/success")
public String loginSuccess(){
return "success";
}
@RequestMapping("/noPermission")
public String noPermission(){
return "noPermission";
}
@RequiresRoles(value = {"admin"})
@RequestMapping("/admin/test")
public @ResponseBody
String adminTest(){
return "/admin/test ";
}
/**
* ,
* @return
*/
@RequiresAuthentication
@RequestMapping("/admin/test01")
public @ResponseBody String adminTest01(){
return "/admin/test01 ";
}
/**
* @RequiresPermissions RequiresRoles
*/
@RequiresPermissions(value={"admin:add"})
@RequestMapping("/admin/add")
public @ResponseBody String adminAdd(){
return "/admin/add ";
}
@RequiresRoles(value = {"user"})
@RequestMapping("/user/test")
public @ResponseBody String userTest(){
return "/user/test ";
}
/**
* authorizationException shiroException
*/
@ExceptionHandler(value={AuthorizationException.class})
public String permissionError(Throwable throwable){
// , throwable
// ,
//
return "noPermission";
}
}
login.htmlログインページ
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script th:src="@{|/js/jquery-1.11.3.min.js|}"></script>
<script th:src="@{|/js/jQuery.md5.js|}"></script>
<script>
$(function(){
$("#loginBut").bind("click",function(){
var v_md5password=$.md5($("#password").val());
$("#md5Password").val(v_md5password)
})
})
</script>
</head>
<body>
<form action="login" method="post">
<input type="text" name="username"><br>
<input type="text" id="password"><br>
<input type="hidden" name="password" id="md5Password">
<input type="submit" value=" " id="loginBut">
</form>
<span style="color: red" th:text="${errorMessage}"></span>
</body>
</html>
noPermission.html権限ページなし
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1> ! !</h1>
</body>
</html>
success.htmlログイン成功ページ
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- shiro -->
<h1 shiro:guest="true"> </h1>
<!-- -->
<shiro:authenticated>
<h1> </h1><br>
</shiro:authenticated>
<a href="/logout"> </a><br><br><br>
<a th:href="@{|/admin/test|}"> admin </a><br>
<a th:href="@{|/admin/test01|}"> admin test01</a><br>
<a th:href="@{|/admin/add|}"> admin add</a><br>
<a th:href="@{|/user/test|}"> user </a><br>
</body>
</html>
このような最も簡単なshiroプロジェクトは構築に成功したが、開発中にshiroフレームワークはこのように使用されないと言いたい.特に、特定のURLに特定のロールと権限が必要な場合、プロファイルに大量に構成され、プロジェクトのメンテナンスコストが増加します.後期URLアドレスは特に多く、私たちのshiroConfigという構成クラスは非常に膨大になる可能性があります.そこで次の一枚はshiroの注釈ベースの開発とよくあるshiroラベル(shiro統合thymeleafの使い方)についてお話ししたいと思います.
–未完待機
OK、週末は楽しかった~