Spring Cloud OAuth2 (i) Build a licensing service

Source: Internet
Author: User
Tags oauth asymmetric encryption

Profile

The main content of this article is the construction of the Spring Cloud Licensing service, using JWT certification.
GitHub Address: Https://github.com/fp2952/spring-cloud-base/tree/master/auth-center/auth-center-provider

Add dependency

OAuth2 extension of Spring Security and security

        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-security</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-oauth2</artifactId>        </dependency>
Start class annotations

Start class Add @EnableAuthorizationServer annotations

@SpringCloudApplication@EnableAuthorizationServer@EnableFeignClients("com.peng.main.client")public class AuthCenterProviderApplication {   public static void main(String[] args){       SpringApplication.run(AuthCenterProviderApplication.class, args);   }}
Oauth2 Configuration Class Authorizationserverconfigureradapter

In Authorizationserverconfigureradapter:

    • Clientdetailsserviceconfigurer: Used to configure the client detail service (Clientdetailsservice), the client details are initialized here, You can write the client details dead here or through a database to store the details of the fetch.
    • Authorizationserversecurityconfigurer: The security constraint used to configure the token endpoint (token Endpoint).
    • Authorizationserverendpointsconfigurer: The access endpoint and token service (token services) used to configure authorization (authorization) and token (tokens).
      The main configuration is as follows:
Configuring Client Detail Information

Clientdetailsserviceconfigurer (a callback configuration entry for Authorizationserverconfigurer) Ability to use memory or JDBC for client detail Services (clientdetailsservice), Spring Security OAUTH2 is configured by writing the @configuration class inheritance Authorizationserverconfigureradapter, and then overriding the Void Configure ( Clientdetailsserviceconfigurer clients) methods, such as:

    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        // 使用JdbcClientDetailsService客户端详情服务        clients.withClientDetails(new JdbcClientDetailsService(dataSource));    }

Here, the client details service is implemented using JDBC, the data source DataSource does not narrate, using the Framework default table, the schema link:
Https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql

Configuring token Management (Jwtaccesstokenconverter)

The

Jwtaccesstokenconverter is the converter used to generate tokens, and the token token is signed by default, and the resource server needs to verify the signature. There are two ways to encrypt and verify:
Symmetric encryption, asymmetric encryption (public key)
Symmetric encryption requires the authorization server and the resource server to store the same key value, and asymmetric encryption can use key encryption, exposing the public key to the resource server verification, the use of asymmetric encryption in this article, Configured on Authorizationserverconfigureradapter as follows:

  @Override public void Configure (Authorizationserverendpointsconfigurer endpoints) {Endpoints.aut Henticationmanager (AuthenticationManager)//Configure Jwtaccesstoken Converter. Accesstokenconverter (Jwtac Cesstokenconverter ())///Refresh_token requires Userdetailsservice. Reuserefreshtokens (false). Userde                Tailsservice (Userdetailsservice);    . Tokenstore (Getjdbctokenstore ()); /** * Use an asymmetric encryption algorithm to sign tokens * @return */@Bean public jwtaccesstokenconverter Jwtaccesstokenconverte        R () {Final Jwtaccesstokenconverter converter = new Jwtaccesstoken (); Import certificate Keystorekeyfactory keystorekeyfactory = new Keystorekeyfactory (New Classpathresource ("Keysto        Re.jks ")," Mypass ". ToCharArray ());        Converter.setkeypair (Keystorekeyfactory.getkeypair ("mytest"));    return converter; }

Generate the JKS certificate file from the JDK tool and put the KEYSTORE.JKS into the resource directory
keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore keystore.jks -storepass mypass

Here we customize Jwtaccesstoken for adding additional user information

/** * Created by fp295 on 2018/4/16. * Custom Jwtaccesstoken Converter */public class Jwtaccesstoken extends Jwtaccesstokenconverter {/** * Generate token * @param a Ccesstoken * @param authentication * @return * */@Override public oauth2accesstoken enhance (oauth2accesst Oken Accesstoken, oauth2authentication authentication) {Defaultoauth2accesstoken Defaultoauth2accesstoken = new De        Faultoauth2accesstoken (Accesstoken);        Set additional user information Baseuser Baseuser = ((Baseuserdetail) Authentication.getprincipal ()). Getbaseuser ();        Baseuser.setpassword (NULL);        Add user information to token extra information defaultoauth2accesstoken.getadditionalinformation (). Put (Constant.user_info, baseuser);    Return Super.enhance (Defaultoauth2accesstoken, authentication); }/** * Parse token * @param value * @param map * @return */@Override public Oauth2accesstoken E Xtractaccesstoken (String value, map<string,?> Map) {Oauth2accesstoken oauth2accessToken = Super.extractaccesstoken (value, map);        Convertdata (Oauth2accesstoken, Oauth2accesstoken.getadditionalinformation ());    return oauth2accesstoken; } private void Convertdata (Oauth2accesstoken accesstoken, map<string,?> Map) {accesstoken.getadditional    Information (). Put (Constant.user_info,convertuserdata (Map.get (Constant.user_info)));        } private Baseuser Convertuserdata (Object map) {String json = Jsonutils.deserializer (map);        Baseuser user = Jsonutils.serializable (JSON, baseuser.class);    return user; }}

The

Jwtaccesstoken class obtains user information from the Getprincipal in the authentication (actually the Userdetails interface), so we need to implement our own userdetails

/** * Created by fp295 on 2018/4/29. * Packaging Org.springframework.security.core.userdetails.User Class */public classes Baseuserdetail implements Userdetails,    Credentialscontainer {private final baseuser baseuser;    Private final Org.springframework.security.core.userdetails.User User;        Public Baseuserdetail (Baseuser baseuser, user user) {this.baseuser = Baseuser;    This.user = user;    } @Override public void Erasecredentials () {user.erasecredentials (); } @Override public collection<?    Extends Grantedauthority> getauthorities () {return user.getauthorities ();    } @Override Public String GetPassword () {return User.getpassword ();    } @Override Public String GetUserName () {return user.getusername ();    } @Override public Boolean isaccountnonexpired () {return user.isaccountnonexpired ();    } @Override public Boolean isaccountnonlocked () {return user.isaccountnonlocked (); } @Override   public Boolean iscredentialsnonexpired () {return user.iscredentialsnonexpired ();    } @Override public Boolean isenabled () {return user.isenabled ();    } public Baseuser Getbaseuser () {return baseuser; }}
Authorized Endpoint Open
    @Override    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {        oauthServer                // 开启/oauth/token_key验证端口无权限访问                .tokenKeyAccess("permitAll()")                // 开启/oauth/check_token验证端口认证权限访问                .checkTokenAccess("isAuthenticated()");    }
Security Configuration

Need to configure Daoauthenticationprovider, Userdetailservice, etc.

@Configuration @order (managementserverproperties.access_override_order) public class Websecurityconfig extends Websecurityconfigureradapter {//auto-inject userdetailsservice @Autowired private Baseuserdetailservice baseuserdetails    Ervice;                @Override public void Configure (Httpsecurity http) throws Exception {http//config landing page/login and allow access                . Formlogin (). Permitall ()//Logout page. and (). Logout (). Logouturl ("/logout"). Logoutsuccessurl ("/") All remaining requests require authentication. and (). Authorizerequests (). Anyrequest (). Authenticated ()//    Since we are using JWT, we do not need csrf. and (). CSRF (). disable ();        }/** * User authentication * @param auth * * * @Override public void Configure (Authenticationmanagerbuilder auth) {    Auth.authenticationprovider (Daoauthenticationprovider ()); } @Bean Public Daoauthenticationprovider Daoauthenticationprovider () {Daoauthenticationprovider Provider = NE W DaoauthenticatiOnprovider ();        Set Userdetailsservice provider.setuserdetailsservice (Baseuserdetailservice);        Suppress hidden user not found exception provider.sethideusernotfoundexceptions (false);        Use Bcrypt for password hash provider.setpasswordencoder (new Bcryptpasswordencoder (6));    return provider; }}
Userdetailsservice implementation
@Servicepublic class Baseuserdetailservice implements Userdetailsservice {private Logger Logger = Loggerfactory.getlog    GER (This.getclass ());    @Autowired private Baseuserservice Baseuserservice;     @Autowired private Baseroleservice Baseroleservice; @Override public userdetails loaduserbyusername (String username) throws Usernamenotfoundexception {//Call FEIGNCL        ient query user responsedata<baseuser> baseuserresponsedata = baseuserservice.getuserbyusername (username); if (baseuserresponsedata.getdata () = = NULL | |!             ResponseCode.SUCCESS.getCode (). Equals (Baseuserresponsedata.getcode ())) {Logger.error ("The user is not found, user name:" + username);        throw new Usernamenotfoundexception ("Could not find the user, user name:" + username);        } baseuser Baseuser = Baseuserresponsedata.getdata (); Call feignclient query role responsedata<list<baserole>> baserolelistresponsedata = BaseRoleService.getRoleByU        Serid (Baseuser.getid ()); List<baserole> ROles;  if (baserolelistresponsedata.getdata () = = NULL | | ! ResponseCode.SUCCESS.getCode (). Equals (Baserolelistresponsedata.getcode ())) {Logger.error ("Query role failed!            ");        roles = new arraylist<> ();        }else {roles = Baserolelistresponsedata.getdata ();        }//Get a list of user rights list<grantedauthority> authorities = new ArrayList (); Roles.foreach (E--{//store user, role information to grantedauthority, and put to grantedauthority list grantedauthority Authori            ty = new Simplegrantedauthority (E.getrolecode ());                Authorities.add (authority);        }); Org.springframework.security.core.userdetails.User user = new Org.springframework.security.core with information about users ' rights . userdetails. User (Baseuser.getusername (), Baseuser.getpassword (), IsActive (Baseuser.getactive ()), True, true, true, auth        Orities);    return new Baseuserdetail (Baseuser, user); } private Boolean isActive (int active) {REturn active = = 1?    True:false; }}
Authorization Server Authentication

http://127.0.0.1:8080/oauth/authorize?client_id=clientId&response_type=code&redirect_uri=www.baidu.com

Note: client_id: For client_id stored in the database, Response_type: Write Dead Code

    1. Enter the simple landing page of spring security after the link returns,

    1. Enter the account password, for the implementation of the Userdetailsservice to get the user, click Login,
    2. Go to the Simple authorization page, click Authorize,
    3. Redirect to Redirect_uri with the code parameter:
      http://www.baidu.com?code=rTKETX
    4. Post request for token:

Note that the request header is added here, and Authorization the value is Basic xxx xxx for client_id:client_secret the base64 encoding, which returns:

Spring Cloud OAuth2 (i) Build a licensing service

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.