关于受权认证请看这篇javascript
后台受权认证弄完了如今搞前台。 模版是用 Angular 的ngx-admin. 效果很酷炫。java
重写了login component, 将原有的那个google ,facebook 等第三方登入先移除掉。查看git
修改方法也很简单,本身重新注册这个component。github
同理 注册页面也是同样的spring
国际化也已经添加 这里就不介绍了。 数据库
下面主要的是代码逻辑。 建议能够先看一下这个文档api
const NB_CORE_PROVIDERS = [ ...DataModule.forRoot().providers, ...NbAuthModule.forRoot({ providers: { email: { service: NbEmailPassAuthProvider, config: { baseEndpoint: '/api', delay: 500, login: { rememberMe: true, endpoint: '/oauth/token', method: 'post', redirect: { success: '/', failure: null, }, defaultErrors: ['auth.login.loginError'], defaultMessages: ['auth.login.loginSuccess'], }, register: { endpoint: '/user/register', method: 'post', redirect: { success: '/', failure: null, }, defaultErrors: 'Register error', defaultMessages: 'Success', }, token: { key: 'access_token', }, }, }, }, forms: { login: { socialLinks: socialLinks, }, register: { socialLinks: socialLinks, }, }, }).providers,
提供一个provider. app
登入 /api/oauth/token ide
注册 /api/user/registerpost
启动的时候几个配置 proxy,
这样当你访问 /api/oauth/token 它会访问 localhost:8080/oauth/token
angular 里面提供的http 请求时候的拦截器,在登入的时候咱们在拦截器里面添加head 属性
/** * Created by fky on 4/4/2018. */ import {Injectable} from '@angular/core'; import {HttpInterceptor, HttpHandler, HttpRequest, HttpEvent} from '@angular/common/http'; import {Md5} from 'ts-md5/dist/md5' import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/do'; import {NbTokenService} from '@nebular/auth/services/token/token.service' import 'rxjs/add/operator/switchMap'; @Injectable() export class RequestInterceptor implements HttpInterceptor { constructor(private nbTokenService: NbTokenService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.url === '/api/oauth/token') { const requestCopy = req.clone({ headers: req.headers .append('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8') //spring auth token 验证须要这个 type .append('authorization', 'Basic dGVzdGp3dGNsaWVudGlkOlhZN2ttem9OemwxMDA='), // 这个是clientid 和client_secret basic body: 'username=' + req.body.email + '&password=' + Md5.hashStr(req.body.password) + '&grant_type=password', }, ); return next.handle(requestCopy); } else if (req.url === '/api/user/register') { const requestCopy = req.clone({ body: { email: req.body.email, username: req.body.username, password: Md5.hashStr(req.body.password), confirmPassword: Md5.hashStr(req.body.confirmPassword), terms: req.body.terms, }, }, ); return next.handle(requestCopy); } else { return this.nbTokenService.get().switchMap(tokenObj => { const token = tokenObj.getValue(); const requestCopy = req.clone({ headers: req.headers .append('Authorization', 'Bearer ' + token), }); return next.handle(requestCopy); }); } } }
登入时候我把密码MD5了一下。
登入的后台验证过程都是spring完成的, 咱们只是以前配置了一下。 逻辑能够看一下源码
类:org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.class
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST) public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException { if (!(principal instanceof Authentication)) { throw new InsufficientAuthenticationException( "There is no client authentication. Try adding an appropriate authentication filter."); } String clientId = getClientId(principal); ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId); TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient); if (clientId != null && !clientId.equals("")) { // Only validate the client details if a client authenticated during this // request. if (!clientId.equals(tokenRequest.getClientId())) { // double check to make sure that the client ID in the token request is the same as that in the // authenticated client throw new InvalidClientException("Given client ID does not match authenticated client"); } } if (authenticatedClient != null) { oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient); } if (!StringUtils.hasText(tokenRequest.getGrantType())) { throw new InvalidRequestException("Missing grant type"); } if (tokenRequest.getGrantType().equals("implicit")) { throw new InvalidGrantException("Implicit grant type not supported from token endpoint"); } if (isAuthCodeRequest(parameters)) { // The scope was requested or determined during the authorization step if (!tokenRequest.getScope().isEmpty()) { logger.debug("Clearing scope of incoming token request"); tokenRequest.setScope(Collections.<String> emptySet()); } } if (isRefreshTokenRequest(parameters)) { // A refresh token has its own default scopes, so we should ignore any added by the factory here. tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE))); } OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest); if (token == null) { throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType()); } return getResponse(token); }
登入成功 返回一串token 值 , 后续验证用户时候只要带这串token 就能够了。
注册 后台controller
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserServcie userService; @RequestMapping(value = "/register", method = RequestMethod.POST) public ResponseEntity<OAuth2AccessToken> register(@RequestBody User user) throws RestException { OAuth2AccessToken token = userService.registerUser(user); HttpHeaders headers = new HttpHeaders(); headers.set("Cache-Control", "no-store"); headers.set("Pragma", "no-cache"); return new ResponseEntity<OAuth2AccessToken>(token, headers, HttpStatus.OK); } }
@Override public OAuth2AccessToken registerUser(User user) throws RestException { User u = userDAO.findByEmail(user.getEmail()); if (u != null) { throw new RestException("User email exist"); } User copy = new User(); BeanUtils.copyProperties(user, copy); // 将获得的 md5 密码再加密一边存数据库 // encode password BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); copy.setPassword(encoder.encode(user.getPassword())); userDAO.registerUser(copy); return createToken(user); } private OAuth2AccessToken createToken(User user) { Map<String,String> param = new HashMap<>(); param.put("username", user.getEmail()); param.put("password", user.getPassword()); param.put("grant_type", grantType); Set<String> scopes = new HashSet<>(); scopes.add(scopeRead); scopes.add(scopeWrite); TokenRequest tokenRequest = new TokenRequest(param, clientId, scopes, grantType); ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId); //user password authentication token Authentication userAuth = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()); param.remove("password"); ((AbstractAuthenticationToken) userAuth).setDetails(param); userAuth = authenticationManager.authenticate(userAuth); return tokenServices.createAccessToken(new OAuth2Authentication(tokenRequest.createOAuth2Request(authenticatedClient), userAuth)); }
写注册时候 成功的时候要返回token 给我一阵好整。 分析了login的整个流程,用新注册的帐号从新模拟再登入一遍。 返回token 前台直接跳到home page.
仓库:https://gitee.com/codefans/fmanager
https://gitee.com/codefans/admin-cli
欢迎小伙伴加入一块儿玩耍