Httpclient's webservice client and session Verification

Source: Internet
Author: User
Tags html header

Welcome to: http://observer.blog.51cto.com

Webservcie is a technology that supports cross-language cross-platform development. servers can be built in various computer languages, and clients can also be developed in various computer languages. If a server is built in java, C ++, or php, other languages can develop the client based on its open wsdl, then, call the method just like calling the method of the local project.
This article uses httpclient to develop the client. The server example depends on the article: clients. This article adds security verification and session usage and permission management on the basis of the original example.
There are many security authentication methods for webservice, including soapheader authentication, integrated windows authentication, and ip binding authentication. Here, the bloggers think that the basic is often the most effective. This article uses a filter to authenticate the logon identity, and then stores the information in the session to maintain the login and permission management, just as after the usual web login.
1. Compile a webservice client Template
First, use httpclient to write a client that can access webservice. For more information, see the source code.
Here, because wsdl, url, encoding, and the returned field names are highly likely to be modified later, the configuration files are used to store their information.

Webservicetest. properties:

webservice.wsdl=http://localhost:8080/webServiceCXF/services/Service?wsdl    webservice.url=http://www.observer.com/service    webservice.encoding=utf-8    webservice.fieldname=result

Then, package a class to read them: com. observer. webservcie. util. ServicePropertiesUtil. For details, you can download the code and view it. Let's just start.
In my previous article: Workshop.
Now that we know this principle, can the httpclient, which can act as a browser in java, access the webservice url and then access webservice? Wait and see.
After session verification is added, the client encapsulation changes. Therefore, write the client template first, and the xml template sent can be automatically generated using soupui, for the use of soupri, see the article about js.
TestWebServiceClient:

Public class TestWebServiceClient {public static void main (String [] args) throws FormatException {ServicePropertiesUtil servicePropertiesUtil = new ServicePropertiesUtil ("webservicetest "); // obtain the ServicePropertiesUtil class StringBuffer sb = new StringBuffer (); sb. append ("<soapenv: Envelope xmlns: soapenv = 'HTTP: // schemas.xmlsoap.org/soap/envelope/'xmlns: ser = '" + servicePropertiesUtil. getWebServiceUrl () + "'>"); sb. append ("<soapenv: Header/>"); sb. append ("<soapenv: Body>"); sb. append ("<ser: getGradeName>"); sb. append ("<toid>"); sb. append (123); sb. append ("</toid>"); sb. append ("</ser: getGradeName>"); sb. append ("</soapenv: Body>"); sb. append ("</soapenv: Envelope>"); // xml HttpClient httpClient = new HttpClient (); // create an HttpClient class PostMethod postMethod = new PostMethod (servicePropertiesUtil. getWebServiceWsdl (); postMethod. setRequestHeader ("SOAPAction", "http://dao.wfservice.ws.emolay.com"); String html = null; try {String out = sb. toString (); postMethod. setRequestEntity (new StringRequestEntity (out, "text/xml", servicePropertiesUtil. getWebServiceEncoding (); // sets the data to be pushed httpClient.exe cuteMethod (postMethod); // access webservcie html = postMethod. getResponseBodyAsString (); // obtain the xml postMethod returned by webserivce. releaseConnection ();} catch (HttpException e) {e. printStackTrace (); throw new FormatException ("connection exception 1", "the server is being maintained. Please try again later, or contact the server maintenance personnel for processing");} catch (IOException e) {throw new FormatException ("connection exception 2", "the server is being maintained. Please try again later or contact the server maintenance personnel for processing");} Document doc = Jsoup. parse (html); // parse xml using jsoup to obtain the data Elements elements = doc returned by webservice. select (servicePropertiesUtil. getWebServiceFieldname (); // parse the data String [] datas = new String [elements. size ()]; int I = 0; for (Element ele: elements) {datas [I] = ele. text (); I ++;} // output data for (String d: datas) {System. out. println (d );}}}

Technically, the comments have been clearly written. I will not talk about them here. The server uses the dependent server webServiceCXF, deploys the server to tomcat, and runs the main method here, the result is "is succeed", which proves that the client code is correctly written and that httpclient can access webservice.
2. Modify the server
First, change the server name to webServiceCXFSession.
Some people may think that if a login method is defined in webservice, webserivce must not be blocked when accessing this method, however, in the filter, it is impossible to know what method your webservice is going to access. Only after the webservice parses the xml passed in can you know it. This is a conflict. What should we do? Here, the blogger first wants to add a parameter such as islogin to the uploaded header file), then obtains the header file information in the filter, and then checks whether to allow the header file based on the header file information. However, this problem occurs again. If someone else overwrites the client and changes all the islogin passed by all the methods to true, and the others remain unchanged, then you can enter webservcie without verification. Finally, the blogger thinks that it is enough to judge and log on directly in the filter, and the user name and password for login can be transmitted in the form of header files.
All right, the login problem is solved. After logging on using the filter, we can determine whether the session has been logged on when islogin is set to false, and the session does include user information, but how can we get the information in the session in the webservice method to determine its permissions? Here we will use a class mentioned in the previous article of the blogger, which is: java. lang. threadLocal. The simple explanation is: whether or not different copies are accessed by different threads in principle for the moment, as long as you know that this effect is achieved). For details, see the API or the previous article: bytes. Well, as long as we define a ThreadLocal in the webservcie implementation class, put the session in it, and then put and remove the session when webservcie enters and comes out, you can obtain different sessions for different users to access webservcie, and then determine their permissions in the method, as shown below:
In GradeServiceImpl:

Private static final ThreadLocal <HttpSession> threadLocal = new ThreadLocal <HttpSession> (); public static void setHttpSession (HttpSession session) {threadLocal. set (session);} public static void removeSession () {threadLocal. remove ();}/*** verify the permission. If it is not an admin user, the return status code "-1" indicates that you do not have the permission to access this method */public String getGradeName (long toid) {HttpSession session = threadLocal. get (); String user = (String) session. getAttribute ("user"); if ("admin ". equals (user) {System. out. println ("business logic");} else {return "-1";} return "is succeed ";}

Then add the filter to web. xml:

<! -- Webserivce filter --> <filter-name> webserviceFilter </filter-name> <filter-class> com. observer. cxf. login. filter. loginFilter </filter-class> </filter> <filter-mapping> <filter-name> webserviceFilter </filter-name> <url-pattern>/services/* </url -pattern> </filter-mapping> <! -- Webserivce Filter end -->

Implementation class for creating a filter: com. observer. cxf. login. filter. LoginFilter:

Public class LoginFilter implements Filter {public void destroy () {}/*** Filter Filtering Method * When the uploaded html header file contains islogin and is true, the user needs to log on, verify logon * When the uploaded html header file contains islogin and is false, it indicates that the user needs to call webservice. * First, verify whether the user has logged on. If the user has logged on, continue, if you do not log on, return notlogin prompting you Not to log on */public void doFilter (ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {HttpServletRequest request = (HttpServl EtRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; HttpSession session = request. getSession (); String islogin = request. getHeader ("islogin"); if ("false ". equals (islogin) {// determine whether to log on or access webservice String user = (String) session. getAttribute ("user"); if (user! = Null) {// determine whether GradeServiceImpl has been logged on. setHttpSession (session); // put the session into the webservice implementation class arg2.doFilter (request, response); GradeServiceImpl. removeSession (); // After webservice access is complete, remove the session return;} else {PrintWriter out = response. getWriter (); out. println ("notlogin"); out. flush (); out. close () ;}} else if ("true ". equals (islogin) {String username = request. getHeader ("username"); String pas Sword = request. getHeader ("password"); // username and password String user = LoginManger in the header file. login (username, password); PrintWriter out = response. getWriter (); if (user! = Null) {session. setAttribute ("user", user); out. println ("islogin");} else {out. println ("notlogin");} out. flush (); out. close () ;}} public void init (FilterConfig arg0) throws ServletException {}}

In the above Code, LoginManger. login (username, password); is the business logic management class for login. Generally, you need to check the database and do not do more here. For details, you can download the source code.
Third: encapsulate the client
The server has already been written. If it can be used, you can simply write the client.
Here, the blogger uses the template mode to write the client, so that after our server is modified, as long as it has not been changed in general, we can only modify the implementation class. Of course, if the server method is added, the abstract class still needs to be written. Generally, the server modifies some configuration files. At this time, the corresponding xml will change, you only need to modify the implementation class. The variable length parameter list is also used here. If the webservice method of the server changes the parameter, you only need to modify the Method Content in the implementation class.
Code:
Abstract class com. observer. webservcie. httpclient. WebServiceClient:

Public abstract class WebServiceClient {public static ServicePropertiesUtil servicePropertiesUtil = new ServicePropertiesUtil ("webservice"); private static String tmpcookies = ""; /*** send a request to webservcie * @ param outXml request the xml data to be pushed * @ return the information returned by the request * @ throws FormatException when the webservice server is closed or the link is unavailable for other reasons when the request fails, * Throw com. observer. webservcie. error. formatException */private String executeMethod (String out Xml) throws FormatException {HttpClient httpClient = new HttpClient (); PostMethod postMethod = new PostMethod (servicePropertiesUtil. getWebServiceWsdl (); postMethod. setRequestHeader ("Cookie", tmpcookies); postMethod. setRequestHeader ("islogin", "false"); postMethod. setRequestHeader ("SOAPAction", "http://dao.wfservice.ws.emolay.com"); String html = null; try {String out = outXml; postMethod. setRequestE Ntity (new StringRequestEntity (out, "text/xml", servicePropertiesUtil. getWebServiceEncoding (); httpClient.exe cuteMethod (postMethod); html = postMethod. getResponseBodyAsString ();} catch (HttpException e) {e. printStackTrace (); throw new FormatException ("connection exception 1", "the server is being maintained. Please try again later, or contact the server maintenance personnel for processing");} catch (IOException e) {throw new FormatException ("connection exception 2", "the server is being maintained. Please try again later, or contact the server maintenance personnel for processing");} finally {PostMethod. releaseConnection ();} return html ;} /*** send a login request to the webservcie server * @ param username * @ param password user password * @ return the server feedback after Successful Logon: islogin * @ throws FormatException when the webservice server is closed or the link is unavailable, or other reasons cause request failure or logon failure, * the com. observer. webservcie. error. formatException */public String login (String username, String password) throws FormatException {HttpClient httpClient = new HttpClient (); PostM Ethod postMethod = new PostMethod (servicePropertiesUtil. getWebServiceWsdl (); postMethod. setRequestHeader ("islogin", "true"); postMethod. setRequestHeader ("username", username); postMethod. setRequestHeader ("password", password); String html = null; try {httpClient.exe cuteMethod (postMethod); html = postMethod. getResponseBodyAsString (); if (html! = Null & "notlogin ". equals (html. trim () {throw new FormatException ("Logon Failed", "username and password error");} Cookie [] cookies = httpClient. getState (). getCookies (); StringBuffer sb = new StringBuffer (); for (Cookie c: cookies) {sb. append (c. toString () + ";") ;}synchronized (this) {tmpcookies = sb. toString () ;}} catch (HttpException e) {e. printStackTrace (); throw new FormatException ("connection exception 1", "the server is being maintained. Please try again later, or contact the server maintenance personnel for processing");} catch (IOException e) {throw new FormatException ("connection exception 2", "the server is being maintained. Please try again later, or contact the server maintenance personnel for processing");} finally {postMethod. releaseConnection ();} return html ;} /*** parse the xml returned by the server to parse the result * @ param xml the xml returned by the server * @ return parsed result set */private String [] parseData (String xml) {Document doc = Jsoup. parse (xml); Elements elements = doc. select (servicePropertiesUtil. getWebServiceFieldname (); String [] datas = new String [elements. size ()]; int I = 0; for (Element ele: elements) {datas [I] = ele. text (); I ++;} return datas;}/*** request in webservice mode, and parse the xml feedback from webservice to get the result * @ param outXml the xml to be sent by the request * @ return returns the xml resolution result returned by webservice * @ throws FormatException when the user is not logged on or * Server A com. observer. webservcie. error. formatException */public String [] send (String outXml) throws FormatException {String xml = executeMethod (outXml); if ("notlogin ". equals (xml. trim () {throw new FormatException ("Logon exception", "Sorry you have not logged on");} return parseData (xml );} /*** obtain the xml abstract method required by the getGradeName method in webservice. This method is used to rewrite the subclass, * You can flexibly change the server parameters. * @ param data: obtain the required parameter for getGradeName in webservice * @ return xml required by the getGradeName method in webservice * @ throws FormatException when * com. observer. webservcie. error. formatException */public abstract String getGradeNameXml (String... data) throws FormatException; /*** webservice requests the template method of the getGradeName Method * @ param data to obtain the parameter required by getGradeName in webservice * @ return returns the data returned by the getGradeName method of webservice * @ throws FormatException when a connection * com. observer. webservcie. error. formatException */public String [] getGradeName (String... data) throws FormatException {String outXml = getGradeNameXml (data); String [] datas = send (outXml); if (datas. length> 0 & "-1 ". equals (datas [0]) {throw new FormatException ("Operation exception", "Sorry You do not have permission to perform this operation") ;}return datas ;}}

Implementation class: com. observer. webservcie. httpclient. impl. WebServiceClientImpl:

Public class WebServiceClientImpl extends WebServiceClient {/*** xml implementation method required to obtain the getGradeName method in webservice * @ param data get the parameter required by getGradeName in webservice * @ return getGradeName in webservice the xml * @ throws FormatException required by the method throws com. observer. webservcie. error. formatException */public String getGradeNameXml (String... toid) throws FormatException {int id; try {id = Integer. valueOf (toid [0]);} catch (Exception e) {throw new FormatException ("parameter error", "the input parameter must be an integer string ");} stringBuffer sb = new StringBuffer (); sb. append ("<soapenv: Envelope xmlns: soapenv = 'HTTP: // schemas.xmlsoap.org/soap/envelope/'xmlns: ser = '" + servicePropertiesUtil. getWebServiceUrl () + "'>"); sb. append ("<soapenv: Header/>"); sb. append ("<soapenv: Body>"); sb. append ("<ser: getGradeName>"); sb. append ("<toid>"); sb. append (id); sb. append ("</toid>"); sb. append ("</ser: getGradeName>"); sb. append ("</soapenv: Body>"); sb. append ("</soapenv: Envelope>"); return sb. toString ();}}

In the above Code, because login and access to webservice are two different codes, so I wrote two methods to connect to webservice. Then, because different httpclient access servers will generate different sessions, the solution is to upload the Cookie of the last access to the httpclient of the next access, so that the server will think that you are still accessing the same session. After the user logs on, the cookie information will be stored in a static variable tmpcookies). If you want to access the cookie next time, put the cookie of this variable into the header file of httpclient, let the server know that you need to use the session just now for access.
Fourth: Test
All right, the server and client have been compiled. Now, let's test it. log on first and then access it. If you do not log on, you can access it:

public class TestClient {    public static void main(String[] args) {        WebServiceClient webServiceClient = new WebServiceClientImpl();        String[] datas1 = null;        String[] datas2 = null;        try {            String login = webServiceClient.login("admin", "admin");            System.out.println(login);            datas1 = webServiceClient.getGradeName("123");            datas2 = webServiceClient.getGradeName("2222");        } catch (FormatException e) {            e.printStackTrace();            System.out.println(e.getDetails());            return;        }        for(String data : datas1){            System.out.println(data);        }        for(String data : datas2){            System.out.println(data);        }    }}

Here, the blogger passed the test. If a friend modifies the client and detects a bug, he can give the next message to see if the problem can be solved.
Fifth: Package the client
The detailed packaging client will not be mentioned here, because this article already has: http://observer.blog.51cto.com/4247416/1238972. You can refer to the subsequent packaging test.
It should be noted that, because the client here uses a third-party dependent package, you can directly put the dependent package into your own jar, but if you do so, when someone else imports the dependency package to your client, conflicts will occur. Therefore, it is generally to write a description document, which third-party packages the client depends on? To use this client, you must import the third-party packages under the project and list the required packages, in the compressed package, the dependent package is also put together like other ssh frameworks.
Now, the method of using httpclient to create a client and using session for user verification has been completed. For details, you can download the attachment code.
Here, the blogger is transformed under the maven server project, because the jar package is too large and the upload is too slow, so there are friends who will not use maven, I am really sorry, but I believe that I can do this step in java. I can write the project myself in this article, and it is no problem to transplant the code and configuration in the project to a common web project.

This article is from the "Observer * unrestrained" blog, please be sure to keep this source http://observer.blog.51cto.com/4267416/1275608

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.