ApiAuthValue authentication mechanism Summary, apiauthvalue authentication mechanism

Source: Internet
Author: User

ApiAuthValue authentication mechanism Summary, apiauthvalue authentication mechanism

I. background

1. Introduction to automatic configuration tool autoconfig

Some configurations vary with the running environment during project development. For example, the configuration of the jdbc driver may be linked to the local database for development in the development environment. The test environment has a dedicated database environment for testing. If an application needs to be deployed in multiple IDCs, these configurations may be different. If you manually modify the configuration during each launch, it is easy to make mistakes, and the cost will increase linearly as the environment increases.

Autoconfig provides a way to dynamically replace configuration information. In addition, the powerful plug-in mechanism of Maven can be combined with the autoconfig mechanism to exert great power. The autoconfig configuration method in pom. xml is as follows:

 

<Plugin> <groupId> com. alibaba. citrus. tool </groupId> <artifactId> autoconfig-maven-plugin </artifactId> <version> 1.2 </version> <configuration> <exploding> true </exploding> <includescriptorpatterns> <autoconf/auto-config.xml </includeDescriptorPattern> <includescriptorpattern> autoconf/conf/auto-config.xml </includeDescriptorPattern> <strong> autoconf/conf/customize-autoconf/auto-config.xml </includeDescriptorPattern> </strong> </configuration> <executions> <execution> <phase> package </phase> <goals> <goal> autoconfig </goal> </goals> </execution> </ executions> </plugin>Pom. xml

 

Convention over Configuration (CoC), Convention is better than Configuration,The above configuration file fully embodies the CoC principles. By default, the plug-in scans autoconf/auto-config.xml or conf/META-INF/autoconf/auto-config.xml files. Autoconfig uses a set of configuration templates to generate specific configurations for different environments. Its core idea is to define some variable configurations as a template and generate specific configuration files from these templates during autoconfig running.

 

Package test; import java. io. inputStream; import java. util. properties; public class Testconfig {/*** read the profile component-beans.properties from classpath and output it to the console */public static void main (String [] args) throws Exception {InputStream is = Testconfig. class. getClassLoader (). getResourceAsStream ("component-beans.properties"); if (is = null) {System. err. println ("Can not load config resource component-beans.pr Operties in classpath ");} else {Properties prop = new Properties (); prop. load (is); is. close (); for (String key: prop. stringPropertyNames () {String value = prop. getProperty (key); if (value! = Null) {System. out. printf ("% s = % s % n", key, value );}}}}}Testconfig. java

 

In the Testconfig. java file, simulate the implementation of reading the configuration file component-beans.properties from classpath, then create the antoconfig description file auto-config.xml andThe component-beans.properties.vm configuration file correspondsTemplate File (the point in the attribute name will be replaced with an underscore during autoconfig execution ).

Generally, configuration is centrally managed, and the central configuration repository is used to store variable content in the database (both text and DB can be used), and then the template engine (such as velocity and jsp) is used) generate the final configuration file and provide http or other types of interfaces for the user to call before the application starts.

2. Apache encryption tool class DigestUtils. md5Hex (String str)

The MD5 algorithm is unidirectional and irreversible. Currently, it can only be cracked through brute force cracking. If the application requires Reversible Encryption, you can use DES, 3DES, AES, RSA, and so on. MD5 is often used to encrypt the user's login password. Each time the user enters the password, it is encrypted with MD5 and compared with the password stored in the database. Reversible Encryption is often used for frontend and backend parameter interaction, backend decryption parameters, query data and return it to the frontend.

MD5 encryption is based on a hash algorithm, also known as a hash algorithm. For example, if 10 is divided by 3, the remainder is one, and 4 is divided by 3, the remainder is unknown. Therefore, md5 cannot be decrypted.

 

Ii. Authentication configuration and initialization

First, configure the bean in the component-beans.xml.vm file and execute the initial method at the container startup to add the url for permission verification to the includeStr collection.

 

<Bean id = "apiValve" class = "com. alibaba. tboss. common. services. login. ApiAuthValve" init-method = "initial"> <! -- Permission verification url --> <property name = "includeStr"> <list> <value> <! [CDATA [^/tboss/web/api/. * \. json $]> </value> </list> </property> <! -- Url to be skipped in the verification module --> <property name = "excludeStr"> <list> </property> </bean>ApiValue Definition

 

Then the ApiAuthValue is configured in the pipeline-web.xml to ensure that the invoke callback method in ApiAuthValue. java is executed when an API call request is made to the system. (Callback function understanding: outsource some functions of the function to others .)

 

<? Xml version = "1.0" encoding = "UTF-8"?> <Beans: beans> <services: pipeline xmlns = "http://www.alibaba.com/schema/services/pipeline/valves"> <! -- Initialize turbine rundata and set the objects (such as rundata and utils) that may be used in pipelineContext to be obtained by valve. --> <PrepareForTurbine/> <! -- Set the context of the log system to print the details of the current request in the log. --> <SetLoggingContext/> <! -- Analyze the URL and obtain the target. --> <AnalyzeURL/> <valve class = "com. alibaba. dragoon. patrol. webx3.DragoonStatValve"/> <! -- Configure ApiAuthValue API authentication --> <valve class = "com. alibaba. tboss. common. services. login. ApiAuthValve"/> <choose> <when> <! -- Determine the current logon type --> <pl-conditions: condition class = "com. alibaba. tboss. common. services. login. loginTypeCondition "/> <valve class =" com. alibaba. tboss. common. services. login. mobileAuthValve "/> </when> <otherwise> <valve class =" com. alibaba. tboss. common. services. login. tbossAuthValve "/> </otherwise> </choose> <! -- Check the csrf token to prevent csrf attacks and repeated submission. If the token in the request and session does not match, an error occurs or the expired page is displayed. --> <CheckCsrfToken/> </services: pipeline> </beans: beans>Pipeline-web.xml

 

Then the callback method in ApiAuthValve. java is implemented.

Package com. alibaba. tboss. common. services. login; import static com. alibaba. tboss. common. auth. costants. apiConstants. API_AUTH_NAME; import static com. alibaba. tboss. common. auth. costants. apiConstants. API_AUTH_SIGNATURE; import static com. alibaba. tboss. common. auth. costants. apiConstants. API_AUTH_TIEMSTAMP; import java. util. arrayList; import java. util. list; import java. util. regex. pattern; import javax. annotation. Resource; import javax. servlet. http. httpServletRequest; import javax. servlet. http. httpServletResponse; import org. slf4j. logger; import org. slf4j. loggerFactory; import org. springframework. beans. factory. annotation. autowired; import com. alibaba. citrus. extension. rpc. impl. defaultResultGenerator; import com. alibaba. citrus. extension. rpc. validation. defaultErrorContext; import com. alibaba. citrus. extension. rpc. val Idation. errorContext; import com. alibaba. citrus. extension. rpc. validation. errorItem; import com. alibaba. citrus. service. pipeline. pipelineContext; import com. alibaba. citrus. service. pipeline. support. abstractValve; import com. alibaba. fastjson. JSON; import com. alibaba. tboss. common. auth. bo. apiUserBo; public class ApiAuthValve extends AbstractValve {private static Logger logger = LoggerFactory. getLogger (ApiAut HValve. class); @ Resource ApiUserBo apiUserBo; @ Autowired private HttpServletRequest request; @ Autowired private HttpServletResponse response; // It must be defined as protected static; otherwise, protected static String [] includeStr cannot be injected; protected static List <Pattern> includes = new ArrayList <Pattern> (); protected static String [] excludeStr; protected static List <Pattern> excludes = new ArrayList <Pattern> (); public void Initial () {if (includeStr! = Null) {for (int I = 0; I <shortdestr. length; I ++) {des. add (Pattern. compile (includeStr [I]. toLowerCase ();} if (excludeStr! = Null) {for (int I = 0; I <excludeStr. length; I ++) {excludes. add (Pattern. compile (excludeStr [I]. toLowerCase () ;}}@ Override public void invoke (PipelineContext pipelineContext) throws Exception {String uri = request. getRequestURI (); try {// isInControl = true indicates that the request link requires authentication if (isInControl (uri) {// external call. Three parameters must be added: apiName, timestamp, signature String apiName = request. getParameter (API_AUTH_NAME); String timestamp = request. getParameter (API_AUTH_TIEMSTAMP); String signature = request. getParameter (API_AUTH_SIGNATURE); // you are not authorized to match apiUserBo from the api_user table. checkAuthorization (apiName, timestamp, signature, uri) ;}} catch (Exception e) {logger. error (uri + "fail-" + e. getMessage (), e); // compromise scheme, dependent on rpc extention ErrorContext errorContext = new DefaultErrorContext (); errorContext. addError (ErrorItem. create ("rpc_500", "500", String. format ("API auth fail:" + e. getMessage (), request. getRequestURI (); Object result = new DefaultResultGenerator. genericWebRPCResult ("API auth fail", null, errorContext); response. getWriter (). print (JSON. toJSONString (result); return;} pipelineContext. invokeNext ();} private boolean isInControl (String uri) {boolean control = false; for (Pattern pattern: includes) {if (pattern. matcher (uri. toLowerCase ()). matches () {control = true; break;} if (control) {for (Pattern pattern: excludes) {if (pattern. matcher (uri. toLowerCase ()). matches () {control = false; break ;}} return control;} public void setRequest (HttpServletRequest request) {this. request = request;} public void setResponse (HttpServletResponse response) {this. response = response;} public String [] getIncludeStr () {return includeStr;} public void setIncludeStr (String [] includeStr) {this. includeStr = includeStr;} public String [] getExcludeStr () {return excludeStr;} public void setExcludeStr (String [] excludeStr) {this. excludeStr = excludeStr ;}}ApiAuthValue. java

Finally, execute the corresponding business logic. The implementation classes of the authentication method are as follows:

 

import org.apache.commons.lang3.time.DateUtils;import com.alibaba.common.lang.MathUtil;import org.apache.commons.codec.digest.DigestUtils;public void checkAuthorization(String apiName, String timestamp, String signature, String uri) {        if(StringUtils.isBlank(apiName) || StringUtils.isBlank(timestamp) || StringUtils.isBlank(signature)) {            throw new ApiAuthException("apiName, timestamp, signature is missing");        }        Date gmtRequest = null;        try {            gmtRequest = DateUtils.parseDate(timestamp, API_AUTH_TIMEFORMAT);        } catch (ParseException e) {            throw new ApiAuthException("Unsupported timestamp format, suggestting as " + API_AUTH_TIMEFORMAT);        }        if (MathUtil.abs(System.currentTimeMillis() - gmtRequest.getTime()) >= 15 * 60 * 1000) {            throw new ApiAuthException("Request has been expired");        }                ApiUser user = getApiUserByName(apiName);        if(user == null) {            throw new ApiAuthException("Api user is not exist");        }        if(!isAuthorized(user, uri)) {            throw new ApiAuthException(String.format("%s has no permission to access uri %s", apiName, uri));        }        String realCode = decode(user.getCode());        String format = String.format("%s%s%s", apiName, timestamp, realCode);        if(!signature.equals(DigestUtils.md5Hex(format))) {            throw new ApiAuthException("Signature is not match");        }    }

 

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.