Small press: The first time I write my own notes, my hands are a bit shaking, the shook ax, huh, huh ~~~ Welcome everyone to throw the brick
Security is
Java advocates the most characteristics, indeed,
Java's security features covers the level of language from the application level and even
JVM itself. I have known that everyone knows.
Sandbox, but only Sandbox is still unsatisfactory, or it is not easy to do all the security needs we need, such as now a system first at least a login function, further words, you need to do behavior for users to access resources Constraint, I think about how Java is doing these things, basically a summary or say "reading after reading", and give a simple implementation example, this example is actually imitating people, huh, huh ...
1. Java access control mechanism
Talk about access control, or "authorize", there are two levels of meaning, one is from the perspective of resources, is this Socket port to be allowed? Is this file readable? Can you write? Is it still possible? Still or more? That's where we use the "LS? L" command in UNIX to list the contents of "-rwx-", the meaning of "-rwx-"; the second is from the visitor's perspective, I want to see Sina Europe on the WEB through the 80-port The news of the cup, is there no such qualification in this system? I want to play a video file called "friends.rm" on the D disk, I got the permission to access this file? Do I have permission to run the player?
Java considers these two aspects while visiting the control strategy, you said, "No, I use
FileOutputStream writes file, use
Socket class connects the remote host to use well, there is nothing limit, "this we have to talk about what is called"
Security Manager
SecurityManger. Security Manager begins with JDK 1.0, how is it! Java considers security factors from the design of the design, the security manager is the most important part of Sandbox, and the general coordinator of access control, we can use the network and files normally in normal case, because when startup When Application (
Note that Application is not applet! ), If you don't add "
-Djava.security.manager option, JVM will not start Sandbox, then you can "do whatever you want", and will not encounter
The exception such as the SECURITYEXCEPTION; once the "-djava.security.manager" option, you will find a series of exceptions!
Exception in thread
"main" java.security.accessControlexception: Access Denied (...)
......
Java has a built-in default security policy. In this case, the security manager is loaded is this default policy. Don't believe it, don't believe you check your "% java_home / jre / lib / security /" directory, is it Have a call
"Java.Policy" file? Take a look with Notepad:
// Standard Extensions Get All Permissions by Default
Grant Codebase
File: $ {java.home} / lib / ext / * "{
Permission java.security.Allpermission;
}
// default permissions granted to all Domains
Grant {
// allows any trread to stop itself using the java.lang.thread.stop ()
// Method That takes no argument.
// Note That this permission is granted by Default Only To Remain
// Backwards compatible.
// it is strongly recommented That You Either Remove this permission
// from this policy file or further restrict it to code Sources
// That You Specify, Because thread.stop () is potentially unsafe.
// See "http://java.sun.com/notes" for more information.
Permission java.lang.RuntimePermission
"stopthread";
// allows anyone to listen on un-priviled ports
Permission java.net.socketpermission
"Localhost: 1024-",
"listen";
// "Standard" Properies That Can Be Read by Anyone
Permission java.util.propertypermission
"java.version",
"read";
Permission java.util.propertypermission
"java.vendor",
"read";
Permission java.util.propertypermission
"java.vendor.URL",
"read";
Permission java.util.propertypermission
"java.class.version",
"read";
Permission java.util.propertypermission
"os.name",
"read";
Permission java.util.propertypermission
"os.version",
"read";
Permission java.util.propertypermission
"os.arch",
"read";
Permission java.util.propertypermission
File.separator,
"read";
Permission java.util.propertypermission
"path.separator",
"read";
Permission java.util.propertypermission
"line.separator",
"read";
Permission java.util.propertypermission
"java.specification.version",
"read"; permission java.util.propertypermission
"java.specification.vendor",
"read";
Permission java.util.propertypermission
"java.specification.name",
"read";
Permission java.util.propertypermission
"java.vm.specification.version",
"read";
Permission java.util.propertypermission
"java.vm.specification.vendor",
"read";
Permission java.util.propertypermission
"java.vm.specification.name",
"read";
Permission java.util.propertypermission
"java.vm.version",
"read";
Permission java.util.propertypermission
"java.vm.vendor",
"read";
Permission java.util.propertypermission
"java.vm.name",
"read";
}
It can be seen that the permissions of the Application assigned in the jar of the sandbox are limited to aborting threads, listening to TCP ports of 1024, and read permissions to some system properties, and permissions like general socket operations and file operations.
We have returned to authorization issues after the concept of the security manager. For the user, the most worrying is that the virus in the machine, the virus is essentially a malicious procedure, so the access control first is to control the permissions of the code. I have always talking about Sandbox, which is called "
Sandbox ", friends who are familiar with Java safety development have probably not unfamiliar, the initial Java is using such a security policy, namely:
The local code is credible, and the remote code is untrustworthy. For example, the applet is a remote code that downloaded from the network to the local and running on the browser, so it is untrustful, so the early applet is completely During Sandbox, the permissions obtained are very limited; after 1.0, the security policy has made some flexible changes until Java 2 appears, and Applet is no longer completely discriminated as "second-class citizen" because of it.
Signing Applet, users can choose to trust this signed applet, so Applet can also do something that is previously considered "out"; to Java 2, the situation has changed, the local code that has always been trusted seems to have become Not that reliably, this is really not allowed, it is difficult to keep who will not go shopping with my girlfriend, sneak in a copy of the virus on your machine, such a local code is falling and remote The code is equivalent, this is more in line with the real world scene, and the security strategy in Java 2 is called "
Configurable security policy, "any code, as long as you are accessible through security manager, you must pre-set access to it, in this other resources or other stuff, sorry,
Java.security.accessControlxception: Access Denied ... This way is not available!
Simply summarize the history of the development of the Java security model, probably the following pictures:
Since it is generally generally a multi-user system, we also hope to be able to constrain the user's behavior, because the factors that cause damage to the system are not just malicious code, people themselves intentionally or unintentional Improper operations will also endanger the system, such as what you said to the upper, others can copy the virus on your machine. If the system can reject this guy's login attempt when you are not there, don't you have a lot? So in the Java security core, it provides a name ""
Java Authentication and Authorization Services, Jaas, Dongdong, dedicated to handle authentication and authorization to users, this is the so-called "
Taking the user-centered authorization model ", it is"
Add a layer on the code-centric authorization model, first of all, users have access to access, then the user can manipulate the code, code to implement a real access operation. Here I mainly tell how JaaS works.
2. Understand a few major APIs
Jaa's API is basically located in Javax.Security.Auth, and it is easy to find in its sub-package.
Javax.Security.Auth.Subject Subject Subject Subject to "the subject" when the system is translated into a "topic", and the Principal, which is sometimes translated into "main body"), Whether it has a few vests, anyway, you can see it as a shadow of your person in Java, your access to the system is reflected as subject.doas () or Subject.doaspriviled () method. Java.security.principal Principal represents an identity object of the user, a user's identity may not only one, his group or the role is also a kind of identity, "Zhang Cuishan" can say "iron clad silver hook", you can say "Zhang Sanfeng's apprentice", can say "Zhang Wuji, he is old", I said "Wudang Qi" and even "Wudang School", of course, this is a group, huh, huh. After a login, you may insert one or more Principal to Subject, this time Subject has the actual meaning, not an empty case. Javax.security.auth.login.loginContext logincontext is designed to provide an open login total interface, you only need to use the policy name obtained from the policy file, and create a logincontext to create a logincontext, then call once login () The method can be logged in, and the login module is transparent here. The javax.security.Auth.spi.loginmodule login module implements the user's authentication logic, its role is to be reflected in the login configuration file, in the later example we will see how to write a login profile and say above Policy file. The LoginModule interface consists of five main methods: Initialize method, initialization module, saves the current Subject and some parameters. Login method, it is determined whether it is certified during a login process. CommT method, whether to submit a login result. Hey, is Login? Do you want to submit it? This is because JAAs uses the process similar to database transaction processing, dividing overall logins into two phases, although you login is successful, but the system still has power to decide to accept you according to your Login's "status". Identity, only through commit, users' Principal will be truly added to Subject,, true yin! The "status" of Login here refers to the "Control Mark" option of the login module in the policy file, which is a bit similar to the concept of priority, because the process of logging in to a system may pass more than one login module, such as our login system input Password, but this password may be saved in a database or LDAP directory, accessing this data source also needs to be authenticated, this will not stop a login module? So what kind of certification process we need to divide is important, which is secondary, the system's acceptance of the user's identity is the result of the comprehensive weighing of these strategies. Abort method: Oops, is it explained above? Let's take a look at Abort, remember the return process of database transaction processing (ROLL BACK)? Abort is a bit like roll back, which means that the system does not accept your identity. The previously done it has been ruled, and the scene is completely exactly the same. Logout method: Logout process, clear internal status, and delete all Principal in Subject.
Javax.security.auth.callback.callbackHandler Pressure is a mechanism for separating interaction processes and certification logic in JaaS, which is also in accordance with OO and loose coupling (Loosely Coupled is a spirit of a trendy word ^ _ ^). JaaS has implemented some common callback objects, including NameCallback obtained by acquiring the user name, and obtains passwordCallback from the password. After getting the textInputCallback input text, you will send textOutputCallback, etc. of the text message, etc.. What we have to do is to implement a CallbackHandler interface. According to different interaction information types, the information obtained from the terminal will be filled in the corresponding Callback. The following example I used a JOPANE prompt text box to enter the username and password. Java.security.privilegedAction said so much login related interface, which is authorized, if we only talk about write source code, then it is very simple, just achieve a privilegedaction interface, cover a run () method, put you want What to do is all amused in this run. But what I said is just a part of the source code, and the license is used in management, such as how to write a policy file. Let's take a look at a complete process of JAAS login and access control. 3. Basic Process JAAS is called "Pluggable Authentication Module, PAMS), in fact, PAM is not a patent, and there is this implementation on Linux, but PAM is indeed earlier in Solaris. System on the system. We look at how JaaS reflects PAM thinking in terms of certification and license: mainly includes such a few part: Users' Principal.class login module (MyCallbackHandler.class) Access code (MyAction). Class) System Inlet (MyFile.TXT) Resource (Login.conf) Login Profile (Jaastest.bat) Since the option is too long, it has been written by the option of starting Java. Shell, run jaastest.bat under the console, select "-djava.security.manager" Specify the security manager to enable the Jaastest class, due to the shell specified option "-djava.security.policy = jaas.policy ", The policy file allows the current code to create loginContext, and authorize other operations, which first initializes a logincontext, option" -djava.security.auth.login.config = login.conf "specifies the login profile, so in current Locate file login.conf in the directory, the login policy name specified in this file is "Jaastest", so the first parameter in logincotext is also "Jaastest", while using our custom callbackhandler.
Create LoginContext successfully, you can log in, call the loginContext's login method, this method finds login module MYLOGINMODULE in login.conf (of course, there are several login modules, here I only use one), execute the login process of the module, MyLoginModule first initialized: login module initializing ... and uses LoginContext to give it a callback object with MYCALLBACKHANDALER, the callback process pops up two graphics dialogs, requires the username and password, we use the specified username "User" and password "LetmePass ", Determination to the current NameCallback and PasswordCallback, then return to myLoginModule's login process, which gets NameCallback and PasswordCallback from the callback object, performs authentication (here is just a simple username and password comparison), MyLoginModule: Authentication Pass! and decide whether to commit, because the login module is defined in login.conf is Required, it is a module that must be successfully authenticated.
MyLoginModule: Add a new principal to current subject. If the overall is passed, then Subject can authorize the code in MyAction, as indicated by statement subject.doas (...), the action of the code is to read the current directory. MyFile.txt file and print its content to the console, notice that the MYPRINCIPAL identity is given to myFile.txt in the policy file JaaS.Policy, so we successfully see Access Success, ACCESS SUCCESSFULLY! Reading file under the console: =========================================== why? Because theater! Because They want to know the truth! Because they Want Their Country Back! Because it still belongs to us as long ask what the beelieve in! ========================================================================================================================================= =========== This is a paragraph in the last graph of the lax of the Garrison passion in the "JFK" I like, huh, huh! The above process we can use a chart to represent: 4. Simple example of the above process using the Java source code and the configuration file as follows: // MyPrincipal.javapackage com.jungleford.auth; import java.security.Principal; public class MyPrincipal implements Principal {// example of a Principal private String name ; // Principal's name public myprincipal (String name) {this.name = name;} public string getName () {// gets the name of Principal Return this.name;} public boolean equals (Object Principal) {// Judgment two a Pincipal same basis if (principal instanceof MyPrincipal) return this.name.equals (((MyPrincipal) principal) .getName ()); else return false;} public String toString () {// Principal represents return "MyPrincipal: " This.name;} public int hashcode () {// Determines the hash value of this object // is used to have a hash container based, it is determined whether or not it is the same object in the hash container.
// If you are interested in Hashcode, see: // http://www-900.ibm.com/developerWorks/cn/java/j-jtp05273/ Return this.name.hashcode ();} // myLoginModule. javapackage com.jungleford.auth; import java.util *;. import java.io.IOException; import java.security.Principal; import javax.security.auth *;. import javax.security.auth.callback *;. import javax .security.auth.login *;. import javax.security.auth.spi *;. public class MyLoginModule implements LoginModule {// private subject subject example of a login module; // login characterized private CallbackHandler cbHandler body; // callback Objects, providing terminals, providing usernames, password interface private map sharedstate; // Used to cache intermediate result private map options; // Some configuration options for saving some login modules need private Boolean successdeded = False; // Successful logo private boolean cmtsucceeded = false; // Overall login successful submission sign private string username; // get username private char [] password; // get password private principal principal; // Identity Sign after login Public Void Initialize (Subject Subject, CallbackHandler Cbhandler, Map SharedState, Map Options) {// Initialization Process System.out.Println ("Login Module Initializing ..."); System.Out.println (); this.subject = Subject; this.cbhandler = CbHandler; this.sharedState = SharedState; this.options = options;} public boolean login () throws LoginException {// single sign-on process if (cbHandler == null) // callback object has not been configured throw new LoginException ( "Error: No CallbackHandler available" "to garner authentication information From the user "); callback [] CBS = new callback [2]; // only use username callback and password callback CBS [0] = new namecallback (" login: "); CBS [1] = new PasswordCallback ("
Password: ", false); try {cbHandler.Handle (CBS); username = ((NameCallback) CBS [0]). Getname (); char [] temp = (PasswordCallback) CBS [1]). GetPassword () ; If (temp == null) {// password is empty Temp = new char [0];} Password = new char [Temp.length]; System.Arraycopy (Temp, 0, Password, 0, Temp.length); . ((PasswordCallback) cbs [1]) clearPassword (); // Clear trace memory password} catch (IOException ioe) {throw new LoginException (ioe.toString ());} catch (UnsupportedCallbackException uce) {throw new LoginException ("Error:" Uce.getCallback (). Tostring () "Not Available To Garner Authentication Information " from the user ");} Boolean usrcorRect = false; // User Name Is correct? Boolean PWDCORRECT = FALSE // Password is correct? If (username.equals ("user")) // currently only allows users named USRCORRECT = true; if (usrcorRect && password.length == 9 && password [0] == ' l '&& Password [1] == 'e' && password [2] == 't' && password [3] == 'm' && password [4] == 'e' && password [5] == 'P' && Password [6] == 'a' && password [7] == 's' & quara // user password specified as letmepass {system.out.println ("MyLoginModule: Authentication Pass ! "); System.out.println (); pwdcorRect = true; success;
Return True; // Login Success} else {system.out.println ("MyLoginModule: Authentication Failed!"); system.out.println (); succeeded = false; username = null; for (int i = 0; i } Return true;} public boolean logout () throws LoginException {// logout, and reset to the state before login subject.getPrincipals () remove (principal);. Succeeded = false; succeeded = cmtSucceeded; username = null; if (password ! = Null) {for (int i = 0; i switch (toc.getMessageType ()) {case TextOutputCallback.INFORMATION: System.out.println (toc.getMessage ()); break; case TextOutputCallback.ERROR: System.out.println ( "Error:" toc.getMessage () ); break; case TextOutputCallback.WARNING: System.out.println ( "Warning:" toc.getMessage ()); break; default: throw new IOException ( "Unsupported message type:" toc.getMessageType ());} } Else if (CBS [i] instanceof namecallback {// prompt the user for a username namecallback nc = (namecallback) CBS [i]; //system.err.print (nc.getPROMPT ()); // system. Err.flush (); nc.setname (username);} else if (CBS [i] instanceof passwordcallback {// prompt the user for sensive information passwordcallback pc = (passwordcallback) CBS [i]; //system.err. PRINT (pc.getprom Pt ()); //system.rr.flush (); pc.setpassword ());} else {throw new unsupportedCallBackexception (CBS [i], "unrecognized callback");}}}} // MyAction.javapackage com.jungleford.auth; import java.io *;. import java.security *;. public class MyAction implements PrivilegedAction {// action public Object run unauthorized access to resources () {// run method must be overriding // Here we assume that the access action is to read the content file file for myfile.txt file in the current directory ("myfile.txt"); string content = ""; try {buffreader reader = new bufferedReader (New FileReader) File); string line = reader.readline (); while (line! = NULL) {Content = line "/ n"; line = reader.readline ();}} catch (exception e) {system.err.println ("error: reclaiming file failed!"); system.rr.println (); e.printStackTrace ();} return content;}} //JAASTest.javapackage com.jungleford.auth; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; public class JAASTest { // Test our JaaS login and authorized shell public static void main (string [] args) {logincontext lc = null; try {// Create context, use custom callback objects, the policy name is jaastest // Simple, only Use a MyLoginModule module lc = new logincontext ("jaastest", new mycallbackhandler ());} catch (exception e) {system.err.println ("error: CREATING LOGIN Context Failed!"); System.rr.println () E.PrintStackTrace (); system.exit (-1);} try {// overall login lc.login ();} catch (Exception E) {system.err.println ("Error: Login Failed!"); System.err.println (); E.PrintStackTrace (); System.exit (-1);} // Get an authorization access object = Subject.doas (lc.getsubject (), new myAction ()); system.out.println ("Access SuccessFully! Reading file:"); system .out.println ("============================================"); System.out.Println (Object ); System.out.println ("============================================"); System.exit ( 0);