Login log
analysis
LoginAuditProcessor records the login log, which can only record the implicit process and mobile phone number jump;
An AuthenticationSuccessEventListener is added to record the password process;
2021-04-02: client_credentials cannot be recorded yet
Authorization code mode is not tested;
Code flow
Bottom up analysis process:
surface: hpfm_audit_login entity: AuditLogin Call for logging Repository, global search : auditLoginRepository. AuditLoginServiceImpl#login AuditLoginServiceImpl#addLoginRecord LoginAuditProcessor#process Two positions: 1. AuthorizationEndpoint#getImplicitGrantResponse 2. LoginTokenService#createAccessToken LoginTokenService#loginForToken - UserLoginServiceImpl#loginMobileForToken - UserLoginServiceImpl#loginOpenForToken
Mobile verification code login
Address: / login/sms
SmsAuthenticationFilter#attemptAuthentication ProviderManager#authenticate SmsAuthenticationProvider#authenticate SmsAuthenticationProvider#additionalAuthenticationChecks CaptchaMessageHelper#checkCaptcha CaptchaMessageHelper#checkCaptchaWithNumber
redis db3, data:
hoth:captcha:user_type_p:default:code:2649ccbfb2c045c2907790b82107e172
Verification code can not be checked:
//During the test, the verification function is disabled and the verification code is not verified //hzero.captcha.testDisable CaptchaMessageHelper#checkCaptchaWithNumber captchaProperties.isTestDisable()
Get token with mobile phone verification code
Call method
SMS login- OAuth Token API
{{gateway}}/oauth/token/mobile?grant_type=implicit&client_id=localhost&client_secret=secret&phone=18009908012&source_type=app&device_id=123456789&captcha=150217&captchaKey=56a7ef80d1f64834a7ab664daa248f38
Code flow
LoginController#loginMobileToken UserLoginServiceImpl#loginMobileForToken LoginTokenService#loginForToken // Encapsulation request parameters Authentication authRequest = attemptAuthentication(request); MobileLoginTokenService#attemptAuthentication SmsAuthenticationToken authRequest = new SmsAuthenticationToken(mobile); //Mobile is the mobile number authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); //The verification code, key and other parameters are in detail Authentication authentication = authenticationProvider.authenticate(authRequest); SmsAuthenticationProvider#authenticate SmsAuthenticationProvider#additionalAuthenticationChecks CaptchaResult captchaResult = captchaMessageHelper.checkCaptcha(captchaKey, inputCaptcha, mobile, getUserType(authentication),businessScope, IospService.Oauth.CODE, false); CaptchaMessageHelper#checkCaptchaWithNumber / / verification code hzero-starter-redis.jar
jwt token,@EnableChoerodonResourceServer
@Enablechorodonresourceserver annotation
The function is to enable resource authentication, parse jwt token and set user information;
Implementation method:
This annotation is used to import configuration classes:
@Import({ChoerodonResourceServerConfiguration.class})
The configuration class inherits from the configuration adapter of spring security:
public class ChoerodonResourceServerConfiguration extends WebSecurityConfigurerAdapter { ...
HttpSecurity is configured in the configuration class, and JwtTokenFilter, jwttokeneextractor, tokenStore, tokenServices, etc. are registered
JwtTokenFilter filter
@An important function of enablechoerodon resource server is to add JwtTokenFilter filter;
JwtTokenFilter is used to parse jwt_token header, set user information to SecurityContextHolder;
The action path of JwtTokenFilter is / v1 / *, which can be configured as follows:
hzero: resource: # Path of JwtTokenFilter application; Note yes / * no/** pattern: /v1/*,/api/* # Path skipped by JwtTokenFilter; Only exact match skip-path: /v2/choerodon/api-docs # If context path is set, it needs to be set to # skip-path: ${server.servlet.context-path}/v2/choerodon/api-docs
The format of pattern is the filter format of servlet, and / v1/*/user is invalid. See the following for details:
My notes:
Key of jwt token
Set key:
ChoerodonResourceServerConfiguration#accessTokenConverter converter.setSigningKey(properties.getOauthJwtKey()); //The default is hzero
This interceptor can generate a token:
(restTemplate and feignClient requests will automatically add jwt_token headers)
...core.net.RequestHeaderCopyInterceptor#intercept token = OAUTH_TOKEN_PREFIX + JwtHelper.encode(objectMapper.writeValueAsString(details.getDecodedDetails()), signer).getEncoded();
By default, HMACSHA256(HS256) algorithm is used, which is symmetric encryption. The key is written to the configuration files hzero.oauthJwtKey and CoreProperties#oauthJwtKey;
HS256 uses the same "secret_key" for signature and verification (symmetric encryption). Once secret_ If the key leaks, there is no security.
- Therefore, HS256 is only suitable for centralized authentication, and signature and verification must be carried out by the trusted party.
- This algorithm is widely used in traditional monomer applications, but please do not use it in any distributed architecture!
JWT signature algorithms HS256, RS256 and ES256 and key generation - in Qingle - blog Park
Customize the return method of client secret error
In case of client secret error, 302 will be returned and redirected to the login page. It is hoped that 401 will be returned to prompt the error message in json format;
Solution: override the SsoAuthenticationEntryPoint defined by hzero OAuth
Call procedure:
BasicAuthenticationFilter //client secret verification failed this.authenticationEntryPoint.commence(request, response, failed); BasicAuthenticationEntryPoint#Comment / / setting 401 ExceptionTranslationFilter#doFilter / / exception of filter is caught ExceptionTranslationFilter#handleSpringSecurityException ExceptionTranslationFilter#sendStartAuthentication authenticationEntryPoint.commence(request, response, reason); SsoAuthenticationEntryPoint#commence response.sendRedirect(redirectUrl);