Safety in J2EE - J2EE Safety Application

xiaoxiao2021-03-06  114

Http://www-900.ibm.com/developerWorks/cn/java/l-j2eeesecurity2/index.shtml

The first part of this series of articles introduced J2EE's security concept, verification model and authorization model, which is more important than the theory. The second part of this article will show the reader to the reader how to apply J2EE security services in the development through a specific example. The focus of this section is to apply and practice.

Note: The purpose of this article describes how to apply the security services provided by J2EE, and is not for specific products. Therefore, the author chooses Sun's J2EE reference implementation (J2SDKee) as a demonstration platform. Because J2SDKee is fully developed in accordance with J2EE specification, although it is unlike J2EE products such as IBM WebSphere, BEA WebLogic, it is definitely the ideal platform for learning J2EE. You can get the latest version of the Sun's J2EE reference implementation via http://java.sun.com/j2ee/. This article selection is Sun's J2SDKee1.3.1.

This article will include the following:

An example using HTTP basic verification An example of an EJB method authorized by a form-based authentication, an example of a programmable security and propagation caller identity

Examples of HTTP basic verification

HTTP Basic Verification is a kind of Web client verification, which controls access to protected resources together with the authorization mechanism of the system.

step:

1. Create a J2EE app

The Application menu item in the New submenu is selected in the FILE menu of the application deployment tool (see Figure 1). The new application dialog box will pop up. Fill in the application file name and application display name (see Figure 2).

figure 1

figure 2

2. Create a web component

In the FILE menu of the application deployment tool, select the Web Compent menu item in the New submenu, which will pop up the New Web Component Wizard dialog (see Figure 3). Select CREATE New WAR File in Application, select the application TEST created in step 1 in the drop-down box, fill in the WebAppTest in the War Display Name box. Click the EIDT button in the Content Bar to select the file containing this web component. There is only one webtest.jsp file in this example. Then click Next to enter the next dialog (see Figure 4). Since our web components are a JSP file, select JSP in the component type. Then press NEXT until the end. At this point we have created a web component containing only one JSP file. Next is the step of configuring security properties.

image 3

Figure 4

3. Configuring security properties

3.1 Creating a security role

The web component WebAppTest created in step 2 in the left navigation bar of the deployment tool, select the Roles property page (see Figure 5) in the property page (see Figure 5). Click the Add button to fill in the security role name User, the Description column in the Name column. The security role represents a collection of users with the same security permission.

Figure 5

3.2 Configuring Security Policy

After creating a security role, you should configure the appropriate security policy on the security role. Click the Security Properties page (see Figure 6).

Figure 6

First select the verification method you want, select Basic from the USER Authentication Method drop-down box. This means you will verify the user through the basic HTTP verification mode. Let's work on Web resources. Click on the Add button in the Security Constraint column to add a security constraint, and the constraint name can be customized. Next, add a web resource to the created constraint. First add a resource collection in Web Resource Collections, then select the resources contained in the resource collection. In this example, the WebTest.jsp file is included in the WRCOLLECTION resource collection, or various files belonging to this web component. Next, which web operations are selected to receive constraints. J2SDKee1.3.1 contains only two operations (GET and POST). Different product supports are different, and the development is the operation provided by the specific product. Now you should specify a security role. Click the Edit button in the Authorized Roles bar to pop up the Security Role List dialog box, and select the defined security role. This example is selected. To this, the security policy has been configured, the following steps are mapping the user and user group mapping in the actual environment with the security role. 4. Mapping

In the left navigation bar, select the application test on the right (see Figure 7), select the user in the Role Name Reference column, click the Add button below, will pop up the user and user group list dialog box, and select A user or group mapped into a safe role user. In this case we map the user J2EE to the security role user. This user J2EE will have access authorization assigned to the security role user.

Figure 7

5. Deployment application

Check the web context property page, fill in TEST in the Context root text box, right-click the application TEST of the left navigation bar, select Deploy to complete the application in the pop-up menu. At this time we have completed all the steps of the first example.

Deployment description file

This example uses the illustrative security service, so we do not need to write any security-related code, but is fully implemented through the deployment description file of the component. Here is the deployment description file of this web component.

'- // Sun microsystems, Inc.//dtd Web Application 2.3 // en'

'http://java.sun.com/dtd/web-app_2_3.dtd'>

WebAppTest // Web Component Name

WebTest

WebTest

/webtest.jsp JSP file included in the component

30

// Security constraint part

// Constrained Web Resource Set WRCOLLECTION // Resource Set Name

/webtest.jsp // resource URL expression

get // Constrained resource operation method

pos

/ / Authorization for security roles

user // security role name

None

// verification mode settings

Basic // uses basic HTTP authentication methods

// Define security roles

this is a user

User

From the deployment description file, this is a web component called WebAppTest, which contains a file called WebTest.jsp, and only the user or user group that is given the user's security role, it has the right to GET or POST operation on WebTest.jsp. There is no connection to the actual user's mapping, and the DTD of the J2EE deployment description file is not defined for the elements of the mapping for security roles and actual users, because there are a variety of different user systems in the actual environment (such as relational databases, System file form and LDAP system, etc.). Therefore, the method of mapping the safety role and the actual user is made by J2EE product vendors.

Test run results

Open IE, enter http: // localhost: 8000 / test // localhost: 8000 / test / webtest.jsp, the verification dialog box will be placed, requiring the user to provide the username and password (see Figure 8), enter the username J2EE and password J2EE. After verifying the JSP file, WebTest.jsp prints "Hello!" (See Figure 9).

Figure 8

Figure 9

Note: Each step is described in detail in the first example, and there will be some operations as the first example in the next example, so only the steps different from the first example will only describe the first example.

Example of form-based verification

Based on form verification and basic HTTP verification, the basic HTTP verification provides the authentication information dialog provided by the browser to collect user authentication information, and the form-based authentication allows custom login pages to collect user authentication information. This example is substantially the same as the first example, and the different places are to provide the landing page and an error page. Login page login.html

There are several places in this file worth noting:

The value of the Action must be "j_security_check" to get the domain name of the username must be "j_username" to get the domain of the user password must be "j_password"

Error page error.html

User name or password is incorrect!

The error page is just a simple display of error messages.

Configuring a form-based verification

First add login.html and error.html into the WebAppTest component. Then see Figure 10 Select the Security Properties page, select the FormBased option in the User Authentication Method drop-down box. Click on Settings ... Pop-pop-up the User Valid Settings dialog, select Login.html at the login page drop, and select Error.html at the Error Page drop-down box.

Figure 10

Re-deploy the app, once again access http: // localhost: 8000 / test / webtest.jsp will appear (see Figure 11), if the username or password is incorrect, Error.html will be displayed to the user.

Figure 11

Deployment description file

'- // Sun microsystems, Inc.//dtd Web Application 2.3 // en'

'http://java.sun.com/dtd/web-app_2_3.dtd'>

WebAppTest

.

.

.

None

form // uses a form-based authentication method

default // uses the default security domain

/login.html // Define login page

/ error.html // Define Maxima

this is a user

User

EJB method authorized example

Safety services for EJB methods are available from J2EE1.3, which is implemented by EJB containers. When the migrator calls the EJB method, the EJB container uses the caller's identity to grant the accesser entry of this caller. If the method of the caller call belongs to the authorization entry, the EJB container call method is called. Otherwise, the EJB container refuses to call this method and returns to the caller to refuse access to an exception. You can authorize the remote method and the Home interface method. In this example, we will authorize a remote method and an HOME interface method.

First create a session bean countejb

Remote interface country.java

Import javax.ejb. *;

Import java.rmi.remoteexception;

Public interface count extends ejbobject {

/ **

* Remote method Count COUNT

* /

Public int count () throws remoteException;

}

HOME interface country.java

Import javax.ejb. *;

Import java.rmi.remoteexception;

/ **

* This is the home interface for countbean.

* One crete () Method is in this Home Interface, Which

* Corresponds to the ejbcreate () Method in The Countbean file.

* /

Public interface counthome extends ejbhome {

/ *

* This Method Creates The EJB Object.

*

* @Param Val Value to Initialize Counter to

*

* @Return the newly created ejb object.

* /

Count create (int valte (int Val) THROWS RemoteException, CreateException;

}

Implement COUNTBEAN.JAVA

Import javax.ejb. *;

Import java.security.principal;

/ **

Public class countBean imports sessionbean {

// The Current Counter is Our Conversational State.

Public int val;

Private sessionContext sessionctX;

//

// Remote business method implementation

Public int count () {

System.out.println ("count ()");

Return Val;

}

//

// HOME interface CREATE method implementation

//

Public void ejbcreate (int val) "

THIS.VAL = VAL;

System.out.println ("ejbcreate ()");}

Public void ejbremove () {

System.out.println ("ejbremove ()");

}

Public void ejbactivate () {

System.out.println ("ejbactivate ()");

}

Public void ejbpassivate () {

System.out.println ("ejbpassivate ()");

}

Public void setsessionContext (sessionContext CTX) {

SessionctX = CTX;

}

}

Client Program Countclient.java

Import javax.ejb. *;

Import javax.naming. *;

Import java.util.properties;

/ **

* This class is a Simple Example of Client Code.

* /

Public class countclient {

Public static void main (String [] args) {

Try {

InitialContext CTX = New InitialContext ();

Counthome Home = (Counthome)

Javax.rmi.PortableRemoteObject.narrow

CTX.lookup ("Java: Comp / Env / Counthome), CountoMe.Class;

INT country = 0;

Count count = NULL;

/ *

Create and execute remote methods

* /

System.out.println ("Instantiating Beans ...");

Count = home.create (country);

CountVal = count.count ();

System.out.println (country);

/ *

Remove country object

* /

Count.remove ();

} catch (exception e) {

System.out.println (E.getMessage ());

E.PrintStackTrace ();

}

}

}

This EJB includes a remote business method count (), we will authorize this method to a safe role. In addition, the Create () method of the HOME interface is also authorized to the security role.

step 1

Compile the above source program and assemble (DEPLOYTOOL.BAT) with J2SDKee1.3.1 (Figure 12).

Figure 12

Step 2: Configure the security role

Before you authorize the method, you must create a secure role that will be authorized. The steps before creating a security role have been introduced, and it is no longer repeated here. In this example we create a security role called Admin.

Step 3: Method Authorization

The process of authorization is the process of determining those safety roles to access a particular method. Method Authorization is generally responsible for application assembly or application deployers. They create different security roles based on business-specific needs and grant these security roles specific access.

Use the mouse to select COUNTBEAN, select the Security property page (Figure 13) on the right window (Figure 13), select the USE CALLER ID in the Security Identity option, means that the EJB container will verify the method call permission with the method calorie. The Run As Specified Role option will be introduced in the "Example of the Disseminator Identity Identity". Since the Admin security role is created in front, you can see the Admin list in the Method Permissions column. First, the remote method count () is authorized. Select the Remote option and select SEL Roles in the Availability column of the count () method, then select the admin list of the count () method. We have authorized remote method count () so far. Next, the CREATE () method of the HOME interface is authorized. Select Remote Home in the Show column, the remaining steps are the same as the count () method. We have licensed the count () method and the create () method to the Admin security role. But this is a logical collection that does not mean a specific user or user group, so we have to do it is to map the security role with the actual user. Step 4: Role mapping

First we need to create a user in our J2EE environment, the user names Tony, the password is 1.

Figure 13

Here we use usernames and passwords to authenticate. We created this user in Default Realm. You can use the command line mode: "RealmTool -Add Tony 1 ENG". For details, see the tool section of the J2SDK1.3.1 document. Next to map the security role to the user. Select the EJB Application CounteJB, select the Security property page in the right window (Figure 14), click the Edit Roles button, select the security role admin. Click the Add button to select Tony users. This has mapped the security role admin and user Tony.

Step 5: Deployment App

Deployment is applied to the local machine, right-click the EJB application Countejb, select the deploy item that pops up the menu, and configure the items as required.

Step 6: Create a client

Creating a client packages the primary and other auxiliary classes of the client program. The creation of the end will be relatively simple, and it is not described here.

Step 7: Run the program

You can now run the client program to verify the authorization of the method. The client program is executed by command runclient.bat -client client JAR package file name -Name primary class. The container of the client program will display a dialog to prompt the user to enter the username and password (Figure 15), fill in the username and password, press OK.

Figure 15

If the username or password does not match the authorized method, there is no permission abnormality (as shown in Figure 16).

Figure 16

COUNTEJB deployment description file EJB.XML

Doctype EJB-JAR PUBLIC

'- // Sun microsystems, Inc.//dtd Enterprise JavaBeans 2.0 // en'

'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>

count

// countbean belongs to Session Bean

countbean // EJB component display name countbean // EJB component name

Counthome // Home Interface

count // Remote Interface

CountBean // Implementation

stateful // countbean belongs to Stateful Bean

Container // CountBean transaction type is container management

// security logo

// countbean uses the caller ID identity

admin // Defines security role admin

// Method COUNT and REMOVE to secure role admin

admin

// method definition

Countbean

Remote

Count

Countbean

Home

remove

java.lang.object

// Do not check the authorization of the following method

Countbean

Remote

getHandle

.

.

.

.

Countbean

Remote

getjbhrome

// Countbean transaction attribute

Countbean

Remote

Count

Required

Examples of programmable security and dissemination caller identity

This routine includes two parts that demonstrate programmable security and caller identity.

Programmable security routine

Programmable security can be applied to the web layer and the EJB layer, which is an iscallerinRole (), getusrPrincipal (), getCallerPrincipal (), getus.ejb.ebcontexT interface, respectively, by javax.servlet.http.httpservletRequest interface, respectively.. Implemented. Public Boolean IsuserinRole (Java.lang.String Role) Method This method is used to determine if the caller belongs to a particular security role, and if it belongs to Returning True, it returns false. The parameter role specifies a safe role. Through this method developer can join its own security logic judgment in program code, enhance J2EE's flexibility in security.

Public java.security.principal getUserPrincipal () Method calls this method to get a java.security.principal object, this object contains the user name by the Principal.getName () method. By calling the getUserPrincipal () method developer can get the caller's username, then perform a specific logic judgment on the caller's username.

Public Java.Security.principal getCallerPrincipal () method and method and method of the public Boolean ISCALLENROLE (Java.lang.String RoleName) are the same.

Below we pass routines to demonstrate the list of usage procedures for these methods: WebTest.jsp

<% @ Page ContentType = "Text / HTML"%>

JSP page </ title> </ head></p> <p><body></p> <p><% - <jsp: usebean id = "beaninstancename" scope = "session" class = "package.class" /> -%></p> <p><% - <jsp: getproperty name = "beaninstancename" property = "protyname" /> -%> Hello!</p> <p>The caller is <% = request.getuserPrincipal (). getname ()%> <% - get the user name of the caller -%></p> <p><% IF ("admin")) {%> <% - Judging whether the caller belongs to "Admin" security role -%></p> <p>The Caller is admin role;</p> <p><%}%></p> <p></ body></p> <p></ html></p> <p>Web.xml</p> <p><? XML Version = "1.0" encoding = "UTF-8"?></p> <p><! DocType web-app public</p> <p>'- // Sun microsystems, Inc.//dtd Web Application 2.3 // en'</p> <p>'http://java.sun.com/dtd/web-app_2_3.dtd'></p> <p><web-app></p> <p><Display-Name> WebApp </ display-name></p> <p><servlet></p> <p><servlet-name> WebTest </ servlet-name></p> <p><Display-Name> WebTest </ display-name></p> <p><jsp-file> /webtest.jsp </ jsp-file></p> <p><Security-Role-Ref></p> <p><role-name> AdminRef </ role-name></p> <p><role-link> admin </ role-link></p> <p></ security-role-ref></p> <p><Security-Role-Ref></p> <p><role-name> GuestRef </ role-name></p> <p><role-link> Guest </ role-link></p> <p></ security-role-ref></p> <p></ servlet></p> <p><session-config></p> <p><session-timeout> 30 </ session-timeout></p> <p></ session-config></p> <p><Welcome-file-list></p> <p><Welcome-File> WebTest.jsp </ welcome-file></p> <p></ welcome-file-list></p> <p><Security-constraint></p> <p><Web-Resource-Collection></p> <p><Web-Resource-Name> Wrcollection </ Web-Resource-Name></p> <p><url-pattern> /webtest.jsp </ url-pattern></p> <p><http-method> get </ http-method></p> <p><http-method> pos </ http-method></p> <p></ Web-Resource-Collection></p> <p><auth-constraint></p> <p><role-name> admin </ role-name></p> <p><role-name> Guest </ role-name> </ auth-connection></p> <p><user-data-connectiont></p> <p><Transport-Guarance> None </ Transport-Guarance></p> <p></ user-data-connectiont></p> <p></ security-connectiont></p> <p><login-config></p> <p><auth-method> Basic </ auth-method></p> <p><realm-name> </ realm-name></p> <p></ login-config></p> <p><security-role></p> <p><role-name> admin </ role-name></p> <p></ security-role></p> <p><security-role></p> <p><role-name> Guest </ role-name></p> <p></ security-role></p> <p></ web-app></p> <p>As can be seen from the content of the web.xml file, only the security role "admin" and "guest" can have the right to POST and GET operations on the webtest.jsp file.</p> <p>operation result:</p> <p>Create a web application, use WebTest.jsp as a web component, and configure web applications according to Web.xml, assign User J2EE to Admin Security roles in the runtime environment, assign the user Tony to guest roles. Publishing web applications to local J2EE Server. Use IE to access WebTest.jsp as verified by user J2EE as shown in Figure 17, and user J2EE belongs to the Admin security role. See Figure 18</p> <p>Figure 17</p> <p>Figure 18</p> <p>If you verify it with a user Tony, the result is shown in Figure 19</p> <p>Figure 19</p> <p>Applying programmable security in EJB is similar to the method in the web, this article is no longer introduced.</p> <p>Propagation caller identity logo</p> <p>This routine will demonstrate how the caller identity is delivered in the calling chain and describes how to apply "Run As" to implement the identity of the caller in the calling chain. This example will use a web component (a JSP file) and two EJB components to form a call chain. Program list: Webtest.jsp</p> <p><% @ Page ContentType = "Text / HTML"%></p> <p><% @ Page Import = "Andy. *"%></p> <p><% @ Page Import = "javax.naming. *"%></p> <p><html></p> <p><head> <title> JSP page </ title> </ head></p> <p><body></p> <p><% - <jsp: usebean id = "beaninstancename" scope = "session" class = "package.class" /> -%></p> <p><% - <jsp: getproperty name = "beaninstancename" property = "protyname" /> -%></p> <p>Hello!</p> <p>The Caller is <% = Request.getuserPrincipal (). getname ()%></p> <p><% IF (Request.Isuserinrole ("admin")))) {%> The Caller is admin role;</p> <p><%}%></p> <p><%</p> <p>Try {</p> <p>Context ctx = new initialContext ();</p> <p>Andy.counethome Home =</p> <p>(Andy.counethome) javax.rmi.portableremoteObject.narrow</p> <p>CTX.lookup ("Java: Comp / Env / Counthome), andy.counethome.class;</p> <p>Andy.count count = home.create (1);</p> <p>Count.count ();</p> <p>} catch (Exception E)</p> <p>{</p> <p>E.PrintStackTrace ();</p> <p>}</p> <p>%></p> <p></ body></p> <p></ html></p> <p>Countbean.java</p> <p>Package andy;</p> <p>Import javax.ejb. *;</p> <p>Import javax.naming. *;</p> <p>Public class countBean imports sessionbean {</p> <p>Public int val;</p> <p>Private sessionContext EJBCXT = NULL;</p> <p>Public int count ()</p> <p>{</p> <p>INT TEMP = 0;</p> <p>System.out.println ("countbean.count ()");</p> <p>// Print the caller name</p> <p>System.out.println ("THE CALLER IS" EJBCXT.GETCALLERPRINCIPAL (). Getname ());</p> <p>/ / Judgment the caller's security role</p> <p>IF (ejbcxt.iscallerinrole ("admin") // adminRef is a reference name of security role admin</p> <p>{</p> <p>System.out.println ("The Caller Is Admin Role");</p> <p>}</p> <p>IF (ejbcxt.iscallerinrole ("GuestRef")) // GuestRef is a reference name of the security role GUEST</p> <p>{</p> <p>System.out.Println ("The Caller IS Guest Role");</p> <p>}</p> <p>IF (ejbcxt.iscallerinrole ("UserRef")) // userRef is a reference name of the security role User</p> <p>{</p> <p>System.out.Println ("The Caller IS User Role");</p> <p>}</p> <p>// Call the remote method of another EJB</p> <p>Try {</p> <p>Context ctx = new initialContext ();</p> <p>Counthome1 home =</p> <p>(Counthome1) javax.rmi.portableremoteObject.narrow</p> <p>CTX.lookup ("java: comp / env / counthome), countome1.class;</p> <p>Count1 count = home.create (1);</p> <p>Temp = count.count ();</p> <p>} catch (Exception E)</p> <p>{</p> <p>E.PrintStackTrace ();</p> <p>}</p> <p>Return TEMP;</p> <p>}</p> <p>Public void ejbcreate (int val) "</p> <p>THIS.VAL = VAL;</p> <p>}</p> <p>Public void ejbremove () {</p> <p>}</p> <p>Public void ejbactivate () {</p> <p>}</p> <p>Public void ejbpassiVate () {}</p> <p>Public void setsessionContext (sessionContext CTX) {</p> <p>EJBCXT = CTX; // Get EJBCONTEXT objects</p> <p>}</p> <p>}</p> <p>Countbean1.java</p> <p>Package andy;</p> <p>Import javax.ejb. *;</p> <p>Public class countbean1 imports sessionBean {</p> <p>Public int val;</p> <p>Private sessionContext EJBCXT = NULL;</p> <p>Public int count () {</p> <p>System.out.println ("countbean1.count ()");</p> <p>System.out.println ("THE CALLER IS" EJBCXT.GETCALLERPRINCIPAL (). Getname ());</p> <p>IF (ejbcxt.iscallerinrole ("admin")))</p> <p>{</p> <p>System.out.println ("The Caller Is Admin Role");</p> <p>}</p> <p>IF (ejbcxt.iscallerinrole ("guestref")))</p> <p>{</p> <p>System.out.Println ("The Caller IS Guest Role");</p> <p>}</p> <p>IF (ejbcxt.iscallerinrole ("userref"))</p> <p>{</p> <p>System.out.Println ("The Caller IS User Role");</p> <p>}</p> <p>Return Val;</p> <p>}</p> <p>Public void ejbcreate (int val) "</p> <p>THIS.VAL = VAL;</p> <p>}</p> <p>Public void ejbremove () {</p> <p>}</p> <p>Public void ejbactivate () {</p> <p>}</p> <p>Public void ejbpassivate () {</p> <p>}</p> <p>Public void setsessionContext (sessionContext CTX) {</p> <p>EJBCXT = CTX;</p> <p>}</p> <p>}</p> <p>The above three files are a web component and the source code for two EJB components. These three components constitute a call chain .Webtest.jsp, first pass the httpservyl () method to get the call Webtest.jsp The user's Principal object, get the user name of the caller through the Principal.getName () method. Then use the httpservletRequest..suserinrole () method to determine if this is a specific security role. COUNTBEAN is a Stateful Sessoinbean, which has a Count () Remote method, write code for obtaining the caller username and judging calling this security role in this remote method, but also the code to call the countBean1 object, how to display the caller identity how to pass and The caller's security role is changed. ThecountBean1 is also a Stateful SessoinBean, which is basically the same as countbean, but it does not contain code that calls other beans.</p> <p>Now we should configure the security properties of each component. We create security roles in component webtest, citing named adminRef, create security role admin and users in component countbean and countbean1, and the reference names are adminRef and userref. WEBTEST The component is configured to "http Basic Authentication" to the security role admin to access WebTest.jsp permission. Set the countBean to Run As Specified Role, select the user's security role. Use the user J2EE to assign the user J2EE to the Admin security role and the User security role. Then release the application to the server. Use the user J2EE to access Webtest.jsp. Execute Result: Client See Figure 20</p> <p>Figure 20</p> <p>Server side: countbean.count () The caller is j2eethe caller is admin () The Caller IS J2EETHE CALLER IS USER ROLE</p> <p>From the operation results, the user who accesses WebTest.jsp is J2EE, and its security role is admin, and the username of visitBean is J2EE, the security role is admin. You can see that the user identity is passed from the web container to the EJB container. Re-see the component The output result of CountBean1, since CountBean is set to Run As Specified Role, the user security role has been changed to the specified security role when the countBean is called down, so we are user. So we will see, call The user name of the component countBean1 is J2EE. The security characteristic of the security role is User.j2ee meets the needs of the same user with different security roles in different applications. Developers can also use this feature to make flexible security logic judgment.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-99982.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="99982" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.037</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'Dc0HdreZIQqWb94m6Aml9fLNCzbxkqXc0JqKn_2BmMmGtwKYmSV5nK56xV5b4lEQiYXsUZHz8208nT5vyE8MU06g_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>