java的Jaas授权与鉴权
文章目錄
- 1.概述
- 2. 概念預(yù)覽
- 3.SecurityManager應(yīng)用場景
- 2. 測試
-
- 2.1 無安全測試
- 2.2 安全測試
-
- 2.1 綁定授權(quán)策略文件
- 3. 其他java權(quán)限
- 4.優(yōu)化
- 5.再次優(yōu)化
- 錯(cuò)誤集錦
-
- 1.1
- 1.2
?
1.概述
Jaas主要負(fù)責(zé)的是?Authentication?和?Authorization。Java平臺(tái)提供的認(rèn)證與授權(quán)服務(wù)(Java Authentication and Authorization Service (JAAS)),能夠控制代碼對敏感或關(guān)鍵資源的訪問,例如文件系統(tǒng),網(wǎng)絡(luò)服務(wù),系統(tǒng)屬性訪問等,加強(qiáng)代碼的安全性。主要包含認(rèn)證與授權(quán)兩部分,認(rèn)證的目的在于可靠安全地確定當(dāng)前是誰在執(zhí)行代碼,代碼可以是一個(gè)應(yīng)用,applet,bean,servlet;授權(quán)的目的在于確定了當(dāng)前執(zhí)行代碼的用戶有什么權(quán)限,資源是否可以進(jìn)行訪問。
Java Authentication Authorization
Service(JAAS,Java驗(yàn)證和授權(quán)API)提供了靈活和可伸縮的機(jī)制來保證客戶端或服務(wù)器端的Java程序。Java早期的安全框架強(qiáng)調(diào)的是
通過驗(yàn)證代碼的來源和作者,保護(hù)用戶避免受到下載下來的代碼的攻擊。JAAS強(qiáng)調(diào)的是通過驗(yàn)證誰在運(yùn)行代碼以及他/她的權(quán)限來保護(hù)系統(tǒng)面受用戶的攻擊。它
讓你能夠?qū)⒁恍?biāo)準(zhǔn)的安全機(jī)制,例如Solaris NIS(網(wǎng)絡(luò)信息服務(wù))、Windows
NT、LDAP(輕量目錄存取協(xié)議),Kerberos等通過一種通用的,可配置的方式集成到系統(tǒng)中。
2. 概念預(yù)覽
3.SecurityManager應(yīng)用場景
當(dāng)運(yùn)行未知的Java程序的時(shí)候,該程序可能有惡意代碼(刪除系統(tǒng)文件、重啟系統(tǒng)等),為了防止運(yùn)行惡意代碼對系統(tǒng)產(chǎn)生影響,需要對運(yùn)行的代碼的權(quán)限進(jìn)行控制,這時(shí)候就要啟用Java安全管理器。
2. 測試
新建一個(gè)項(xiàng)目JavaJaasTest,路徑為:/Users/lcc/IdeaProjects/JavaJaasTest
2.1 無安全測試
新建測試類?com.security.App1
public class App1 { public static void main(String[] args) { System.out.println(System.getProperty("java.home")); } }- 1
- 2
- 3
- 4
- 5
- 6
運(yùn)行結(jié)果
/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre- 1
2.2 安全測試
新建測試類?com.security.App2
public class App2 {public static void main(String[] args) {//安裝安全管理器System.setSecurityManager(new SecurityManager());System.out.println(System.getProperty("java.home"));}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
運(yùn)行結(jié)果
Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.home" "read")at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)at java.security.AccessController.checkPermission(AccessController.java:884)at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)at java.lang.System.getProperty(System.java:717)at com.security.App2.main(App2.java:15)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
異常提示沒有對java.home的讀取權(quán)限,系統(tǒng)屬性也是一種資源,與文件訪問類似;默認(rèn)情況下對于普通Java應(yīng)用是沒有安裝安全管理器,在手動(dòng)安裝安全管理器后,如果沒有為應(yīng)用授權(quán)則沒有任何權(quán)限,所以應(yīng)用無法訪問java.home系統(tǒng)屬性。
2.1 綁定授權(quán)策略文件
授權(quán)的方式是為安全管理器綁定一個(gè)授權(quán)策略文件。由于我是在IDEA maven Java工程中直接運(yùn)行main方法,所以就在工程根目錄下(/Users/lcc/IdeaProjects/JavaJaasTest/demo.policy)新建一個(gè)demo.policy文件,文件內(nèi)容如下:
grant {permission java.util.PropertyPermission "java.home", "read"; };- 1
- 2
- 3
該授權(quán)的效果是任何用戶運(yùn)行的任何程序都有對java.home的讀權(quán)限,policy文件的具體格式請參看:
http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html
為安全管理器綁定policy文件的方式有兩種:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這兩種方法都是可以得到正確結(jié)果的。
3. 其他java權(quán)限
在Java中權(quán)限有很多,具體可參考
http://docs.oracle.com/javase/7/docs/technotes/guides/security/spec/security-spec.doc3.html#17001
| java.security.AllPermission | 所有權(quán)限的集合 |
| java.util.PropertyPermission | 系統(tǒng)/環(huán)境屬性權(quán)限 |
| java.lang.RuntimePermission | 運(yùn)行時(shí)權(quán)限 |
| java.net.SocketPermission | Socket權(quán)限 |
| java.io.FilePermission | 文件權(quán)限,包括讀寫,刪除,執(zhí)行 |
| java.io.SerializablePermission | 序列化權(quán)限 |
| java.lang.reflect.ReflectPermission | 反射權(quán)限 |
| java.security.UnresolvedPermission | 未解析的權(quán)限 |
| java.net.NetPermission | 網(wǎng)絡(luò)權(quán)限 |
| java.awt.AWTPermission | AWT權(quán)限 |
| java.sql.SQLPermission | 數(shù)據(jù)庫sql權(quán)限 |
| java.security.SecurityPermission | 安全控制方面的權(quán)限 |
| java.util.logging.LoggingPermission | 日志控制權(quán)限 |
| javax.net.ssl.SSLPermission | 安全連接權(quán)限 |
| javax.security.auth.AuthPermission | 認(rèn)證權(quán)限 |
| javax.sound.sampled.AudioPermission | 音頻系統(tǒng)資源的訪問權(quán)限 |
4.優(yōu)化
在上述過程中雖然完成了授權(quán),但授權(quán)的針對性不強(qiáng),在程序綁定了該policy文件后,無論是哪個(gè)用戶執(zhí)行都將擁有java.home系統(tǒng)屬性的讀權(quán)限,現(xiàn)在我們希望做更加細(xì)粒度的權(quán)限控制,這里需要用到認(rèn)證服務(wù)了。
認(rèn)證服務(wù)有點(diǎn)“麻煩”,一般情況下主要都涉及到了LoginContext,LoginModule,CallbackHandler,Principal,后三者還需要開發(fā)者自己實(shí)現(xiàn)。這里先解釋一下這幾個(gè)類的作用:
下面看一個(gè)認(rèn)證例子:
package com.security;import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException;/*** @Author: chuanchuan.lcc* @CreateDate: 2018/12/28 PM4:30* @Version: 1.0* @Description: java類作用描述:*/ public class App4 {public static void main(String[] args) {System.setProperty("java.security.auth.login.config", "/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo.config");System.setProperty("java.security.policy", "/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo.policy");System.setSecurityManager(new SecurityManager());try {//創(chuàng)建登錄上下文LoginContext context = new LoginContext("demo", new DemoCallbackHander());//進(jìn)行登錄,登錄不成功則系統(tǒng)退出context.login();} catch (LoginException le) {System.err.println("Cannot create LoginContext. " + le.getMessage());System.exit(-1);} catch (SecurityException se) {System.err.println("Cannot create LoginContext. " + se.getMessage());System.exit(-1);}//訪問資源System.out.println(System.getProperty("java.home"));} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
使用認(rèn)證服務(wù)時(shí),需要綁定一個(gè)認(rèn)證配置文件,在例子中通過System.setProperty(“java.security.auth.login.config”, “demo.config”);實(shí)現(xiàn),當(dāng)然也可以設(shè)置虛擬屬性-Djava.security.auth.login.config=demo.config實(shí)現(xiàn)。配置文件內(nèi)容如下:
/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo.config
demo {com.security.DemoLoginModule required debug=true; };- 1
- 2
- 3
其中demo為配置名稱,其內(nèi)容指定了需要使用到哪登錄模塊(LoginModule),認(rèn)證配置文件具體格式請參看:http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html
前面說到認(rèn)證與授權(quán)密不可分,這里就可以說明,在創(chuàng)建LoginContext對象時(shí)就需要有createLoginContext.demo的認(rèn)證權(quán)限,demo就是認(rèn)證配置文件中的配置名稱,該名稱在構(gòu)造LoginContext對象時(shí)指定。由于在DemoLoginModule中修改了Subject的principals集合,還需要有modifyPrincipals認(rèn)證權(quán)限,所以授權(quán)策略文件內(nèi)容變?yōu)?#xff1a;
/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo.policy
grant {permission javax.security.auth.AuthPermission "createLoginContext.demo";permission javax.security.auth.AuthPermission "modifyPrincipals";permission java.util.PropertyPermission "java.home", "read"; };- 1
- 2
- 3
- 4
- 5
再次運(yùn)行程序,java.home系統(tǒng)屬性正常輸出
5.再次優(yōu)化
主類修改
package com.security;import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import java.security.Principal; import java.security.PrivilegedAction;/*** @Author: chuanchuan.lcc* @CreateDate: 2018/12/28 PM4:47* @Version: 1.0* @Description: java類作用描述:*/ public class App5 {public static void main(String[] args) {System.setProperty("java.security.auth.login.config", "/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo5.config");System.setProperty("java.security.policy", "/Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo5.policy");System.setSecurityManager(new SecurityManager());LoginContext context = null;try {//創(chuàng)建登錄上下文context = new LoginContext("Demo", new DemoCallbackHander());//進(jìn)行登錄,登錄不成功則系統(tǒng)退出context.login();} catch (LoginException le) {System.err.println("Cannot create LoginContext. " + le.getMessage());System.exit(-1);} catch (SecurityException se) {System.err.println("Cannot create LoginContext. " + se.getMessage());System.exit(-1);}//訪問資源Subject subject = context.getSubject();System.out.println(subject);for (Principal principal : subject.getPrincipals()) {System.out.println("\t" + principal.toString());}DemoPrivilegedAction demoPrivilegedAction = new DemoPrivilegedAction();//該方法調(diào)用需要"doAsPrivileged"權(quán)限Subject.doAsPrivileged(subject, new PrivilegedAction<Object>() {@Overridepublic Object run() {System.out.println(System.getProperty("java.home"));return null;}}, null);} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
在運(yùn)行這段代碼時(shí),后臺(tái)進(jìn)行了以下的工作。
項(xiàng),然后更具該項(xiàng)的內(nèi)容決定該加載哪個(gè)LoginModule對象。
法。
,獲得用戶輸入。
配置
# 路徑 /Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo5.configDemo {com.security.DemoLoginModule required debug=true; };- 1
- 2
- 3
- 4
- 5
配置
# 路徑 /Users/lcc/IdeaProjects/JavaJaasTest/src/main/resources/demo5.policygrant {permission javax.security.auth.AuthPermission "createLoginContext.Demo";permission javax.security.auth.AuthPermission "modifyPrincipals";permission javax.security.auth.AuthPermission "doAsPrivileged"; }; // JAAS 授權(quán),授權(quán)給指定的用戶或身份 grant Principal com.security.DemoPrincipal "zhangsan" {permission java.util.PropertyPermission "java.home", "read"; };- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
報(bào)錯(cuò)
Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.home" "read")at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)at java.security.AccessController.checkPermission(AccessController.java:884)at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)at java.lang.System.getProperty(System.java:717)at com.security.App5$1.run(App5.java:46)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAsPrivileged(Subject.java:483)at com.security.App5.main(App5.java:43)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
這個(gè)原因是因?yàn)閏om.security.DemoPrincipal需要覆寫·equals?和?hashCode方法,修改類
package com.security;import java.security.Principal;public class DemoPrincipal implements Principal {private String name;public DemoPrincipal(String name) {this.name = name;}@Overridepublic String getName() {return this.name;}public boolean equals(Object o) {if (o == null)return false;if (this == o)return true;if (!(o instanceof DemoPrincipal))return false;DemoPrincipal that = (DemoPrincipal) o;if (this.getName().equals(that.getName()))return true;return false;}public int hashCode() {return name.hashCode();}@Overridepublic String toString() {return "DemoPrincipal{" +"name='" + name + '\'' +'}';} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
然后運(yùn)行成功
主體: 主用戶: DemoPrincipal{name='zhangsan'}DemoPrincipal{name='zhangsan'} /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre- 1
- 2
- 3
- 4
- 5
- 6
錯(cuò)誤集錦
1.1
Cannot create LoginContext. access denied ("javax.security.auth.AuthPermission" "createLoginContext.myperson")- 1
- 2
1.2
javax.security.auth.login.LoginException: 沒有為CountFiles配置 LoginModules- 1
參考:
https://blog.csdn.net/xiaolangfanhua/article/details/52835920
https://www.ibm.com/developerworks/cn/java/j-javaauth/
https://www.programcreek.com/java-api-examples/index.php?api=java.security.PrivilegedExceptionAction
總結(jié)
以上是生活随笔為你收集整理的java的Jaas授权与鉴权的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 581. Shortest Unsort
- 下一篇: 【图像处理】——改变图像的大小(降采样重