春のクラウドセキュリティサービスの戦闘マイクロ_5-1_シングルサインオンの基本的なインフラ

 

 

 

以下は、半デタッチアーキテクチャであり、正確には、アーキテクチャの分離の終了前後に共通であり、このアーキテクチャでいくつかの問題があります。

1、SEO、検索エンジンは、これだけのアーキテクチャであればそう、SEOの問題を抱えている、JSに動的にレンダリングされたコンテンツを識別することは不可能である、HTML DOMツリーを登り、静的なHTMLのリソースを認識することができます

2、ブラウザのページのレンダリングが完了するには、ビジネスの複雑な場合は、データの量に、ブラウザはストレスが原因である可能性があり、可能カトンは。

 

 フロントオーバー建築問題と分離の後端を考えると、私たちが取りたい構造の前端と後端の分離は、次のフレームワークです。

 

主な違いは、nodejsはnginxののすべての機能を実現することができ、nginxのはnodeJSを交換しています。

しかし、また、サーバ側ページ・レンダリングなどの他の機能を提供し、ブラウザがHTMLリソースを要求すると、nodejsは、この時点では、ブラウザに、nodejs良いページのレンダリングには、レンダリングされたページを、APIリクエストを送信することができますSEOを行う際に、検索エンジンの上昇は全ページです。一部のページがSEOを必要としない場合、あなたはまだサポートされていますどちらも、ブラウザでページをレンダリングするために、APIを直接ページを送信することができます。

 

 

この実験では、代わりにspringbootのNodeJSの HTMLのJSを使用して、ページ。シリーズの記事の前に、郵便配達が今から、クライアントアプリケーションとして使用され、実用的なフロントエンドアプリケーションで郵便配達を置き換えます。

全体的にこのアーキテクチャは以下の通りであります:

 コードをノックしてみましょうスタート

 1、新しいアプリケーションNB-adminの

 

 

効果:

ディスプレイ、ログインしていない場合には

 

 

 、クリックしてログインするユーザー名とパスワードを入力してください

 

 (認証サーバハードコードパスワードは123456あなたが可能です)

 

 ログイン後:

メインコード:AdminController、ログオン要求内のセッションは、フロントエンドサーバーの上で取得した後、ゲートウェイ、アクセストークンを呼び出します

@ResponseBody
    @PostMapping("/login")
    public void login(@RequestParam String username,@RequestParam String password/*@RequestBody Credential credential*/, HttpSession session){

        //认证服务器验token地址 /oauth/check_token 是  spring .security.oauth2的验token端点
        String oauthServiceUrl = "http://localhost:9070/token/oauth/token";

        HttpHeaders headers = new HttpHeaders();//org.springframework.http.HttpHeaders
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);//不是json请求
        //网关的appId,appSecret,需要在数据库oauth_client_details注册
        headers.setBasicAuth("admin","123456");

        MultiValueMap<String,String> params = new LinkedMultiValueMap<>();
        params.add("username",username);
        params.add("password",password);
        params.add("grant_type","password");
        params.add("scope","read write");

        HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<>(params,headers);
        ResponseEntity<AccessToken> response = restTemplate.exchange(oauthServiceUrl, HttpMethod.POST, entity, AccessToken.class);

        session.setAttribute("token",response.getBody());
        log.info("token info : {}",response.getBody().toString());
    }

在 index.html 里,进页面就发一个/me 请求,如果能从session获取到token信息(先这么干),说明登录成功:

@GetMapping("/me")
    @ResponseBody
    public AccessToken me(HttpSession session){
        AccessToken accessToken = (AccessToken) session.getAttribute("token");
        return accessToken;
    }

index.html

 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
    <h1>欢迎来到sso子系统1</h1>
    <div id="loginTip"></div>
    <p><button onclick="getOrderInfo()">获取订单信息</button></p>

    <table>
        <tr><td>order id</td><td><input id="orderId" /></td></tr>
        <tr><td>order product id</td><td><input id="productId" /></td></tr>
    </table>




</body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>

    function getOrderInfo(){
        $.get("api/order/orders/1",function(data){
            $("#orderId").val(data.id);
            $("#productId").val(data.productId);
        });
    }

    $(document).ready(function(){

        $.get("/me",function(data,status){
            if(data){
                //已登录
                var htm = "已登录,<a href='/logout'>退出</a>";
                $("#loginTip").html(htm);
            }else{
                //未登录
                var href = "<a href='/loginPage'>未登录,去登录</a>";
                $("#loginTip").append(href);
            }
        });
    });

</script>
</html>

 

 

 

login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>

    <center>
        <h3>登录</h3>
        <table border="1">
            <tr>
                <td>用户名</td>
                <td><input id="username" name="username" value="lhy"/></td>
            </tr>
            <tr>
                <td>密码</td>
                <td><input id="password" name="password" value="123456"/></td>
            </tr>
            <tr>
                <td colspan="2" align="right"><button id="submitBtn" onclick="login()">登录</button></td>
            </tr>
        </table>
    </center>
</body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
    function login() {
        var username = $("#username").val();
        var password = $("#password").val();
        //alert(username+", " +password)

        $.ajax({
            type: "POST",
            url: "/login",
            data: {"username":username, "password":password},
            success: function(msg){
                location.href = "/index";
            },
            error:function(msg){
                alert("登录失败!!")
            }
        });
    }

</script>
</html>

 

 请求转发

在nb-admin上,index.html,加上获取订单信息,点击获取订单按钮,发一个请求到前端服务nb-admin,nb-admin配上zuul网关,让它把这个请求转发到网关去,由网关再去请求订单服务,获取订单信息。

在nb-admin项目加入zuul依赖:

<dependency>
     <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

启动类加上注解:

@EnableZuulProxy

配置zuul路由,以 /api 开头的请求,转发到网关

zuul:
  routes: #路由的配置是个Map,可以配置多个
    api:  #api开头的请求,都转发到网关9070
      url:  http://gateway.nb.com:9070
  sensitive-headers:  null  #设置敏感头设置为空,Authorization等请求头的请求,都往后转发

server:
  port: 8080
spring:
  application:
    name: admin

注:几个项目都配置了host,以方便区分cookie等

127.0.0.1 gateway.nb.com    ----网关

127.0.0.1 admin.nb.com  ----前端服务

127.0.0.1 auth.nb.com    ----认证服务

127.0.0.1 order.nb.com  ----订单服务

网关上,获取订单信息,是需要token的,所以在nb-admin上,需要从session中获取到token,加在请求头里,再发往网关。新建一个zuulFilter,统一在请求头加token。

SessionTokenFilter
package com.nb.security.admin;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 从session获取token,统一加到请求头中去
 */
@Component
public class SessionTokenFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        AccessToken accessToken = (AccessToken)request.getSession().getAttribute("token");
        if(accessToken != null){
            requestContext.addZuulRequestHeader("Authorization","Bearer "+accessToken.getAccess_token());
        }
        return null;
    }
}

AccessToken

import lombok.Data;

import java.util.Date;

/**
 * access_token
 * Created by: 李浩洋 on 2020-01-02
 **/
@Data
public class AccessToken {

    private String access_token;

    private String token_type;

    private Date expires_in;

    private String scope;
}

现在效果:

 

 

 登录:

 

 

 登录后

 

 

点击获取订单信息,会发一个  api/order/orders/1 请求,由于nb-admin里配置了zuul路由,api开头的请求都会转发到网关,所以这里实际访问了网关,网关又转发到了order-api,最终返回orderInfo

function getOrderInfo(){
        $.get("api/order/orders/1",function(data){
            $("#orderId").val(data.id);
            $("#productId").val(data.productId);
        });
    }

退出登录

退出登录很简单,直接发一个请求,将nb-admin里的session失效,就行了
@GetMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "index";
    }

 

目前已经用 springboot实现了一个前端服务器,实现了oauth协议中 password模式的登录,请求转发,退出。目前还存在不少问题,下节讲解问题并解决。

(其实我认为将这个就当做某个系统的后端服务也没啥问题,类似于你去微信申请客户端应用一样,这里的nb-admin就是我们自己的公众号项目)

 

代码github:https://github.com/lhy1234/springcloud-security/tree/chapt-5-1-ui

如果对你有一点,就给个小星星吧

おすすめ

転載: www.cnblogs.com/lihaoyang/p/12129852.html