当前位置: 首页 > news >正文

一步一步构建自己的管理系统之 ------登入注册

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

关于授权认证请看这篇

后台授权认证弄完了现在搞前台。 模版是用 Angular  的ngx-admin.  效果很酷炫。

215613_rNBz_241688.png

重写了login component, 将原有的那个google ,facebook 等第三方登入先移除掉。查看

修改方法也很简单,自己从新注册这个component。

同理 注册页面也是一样的

220502_q8Ir_241688.png

国际化也已经添加 这里就不介绍了。 

下面主要的是代码逻辑。  建议可以先看一下这个文档

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. 

登入   /api/oauth/token  

注册  /api/user/register

启动的时候几个配置  proxy,

221522_IIRH_241688.png

这样当你访问  /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

欢迎小伙伴加入一起玩耍

 

 

 

 

 

转载于:https://my.oschina.net/u/241688/blog/1796475

相关文章:

  • 64位linux安装wine等软件
  • javascript 日期函数
  • spring IOC AOP实现原理
  • Python数据挖掘与机器学习技术入门实战
  • 万达酒店及度假村首创微信智能开票辅助功能
  • 【vue】vue +element 搭建项目,vuex中的store使用
  • 面向对象进阶------模块 json pickle hashlib
  • ApiLeaf·可能是史上最省事的文档生成工具
  • CSDN日报20170226——《你离心想事成仅仅差一个计划》
  • 云服务能力评估“国标”出炉,新华三首批通过增强级认证
  • 会话管理(session)
  • 在Office应用中打开WPF窗体并且让子窗体显示在Office应用上
  • 分享一款本地音乐播放器源码
  • Swoft 源码剖析 - 代码自动更新机制
  • 深度学习(五)基于tensorflow实现简单卷积神经网络Lenet5
  • angular组件开发
  • Date型的使用
  • Hibernate最全面试题
  • IDEA常用插件整理
  • input的行数自动增减
  • magento 货币换算
  • Spring-boot 启动时碰到的错误
  • SQLServer之创建数据库快照
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 包装类对象
  • 精彩代码 vue.js
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 算法-图和图算法
  • 微服务框架lagom
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • # Apache SeaTunnel 究竟是什么?
  • # C++之functional库用法整理
  • #控制台大学课堂点名问题_课堂随机点名
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (待修改)PyG安装步骤
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (排序详解之 堆排序)
  • (算法)N皇后问题
  • (一)Java算法:二分查找
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net的socket示例
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)