1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        OAuth2實(shí)現(xiàn)單點(diǎn)登錄SSO完整教程,其實(shí)不難!

        共 42794字,需瀏覽 86分鐘

         ·

        2021-03-19 12:01

        來源:cnblogs.com/cjsblog/p/10548022.html

        前言

        技術(shù)這東西吧,看別人寫的好像很簡單似的,到自己去寫的時(shí)候就各種問題,“一看就會(huì),一做就錯(cuò)”。網(wǎng)上關(guān)于實(shí)現(xiàn)SSO的文章一大堆,但是當(dāng)你真的照著寫的時(shí)候就會(huì)發(fā)現(xiàn)根本不是那么回事兒,簡直讓人抓狂,尤其是對(duì)于我這樣的菜鳥。幾經(jīng)曲折,終于搞定了,決定記錄下來,以便后續(xù)查看。先來看一下效果

        img
        img
        img

        準(zhǔn)備

        2.1. 單點(diǎn)登錄

        最常見的例子是,我們打開淘寶APP,首頁就會(huì)有天貓、聚劃算等服務(wù)的鏈接,當(dāng)你點(diǎn)擊以后就直接跳過去了,并沒有讓你再登錄一次

        img

        下面這個(gè)圖是我再網(wǎng)上找的,我覺得畫得比較明白:

        img

        可惜有點(diǎn)兒不清晰,于是我又畫了個(gè)簡版的:

        重要的是理解:

        • SSO服務(wù)端和SSO客戶端直接是通過授權(quán)以后發(fā)放Token的形式來訪問受保護(hù)的資源
        • 相對(duì)于瀏覽器來說,業(yè)務(wù)系統(tǒng)是服務(wù)端,相對(duì)于SSO服務(wù)端來說,業(yè)務(wù)系統(tǒng)是客戶端
        • 瀏覽器和業(yè)務(wù)系統(tǒng)之間通過會(huì)話正常訪問
        • 不是每次瀏覽器請(qǐng)求都要去SSO服務(wù)端去驗(yàn)證,只要瀏覽器和它所訪問的服務(wù)端的會(huì)話有效它就可以正常訪問
        img

        2.2. OAuth2

        推薦以下幾篇博客

        《OAuth 2.0》 https://www.cnblogs.com/cjsblog/p/9174797.html

        《Spring Security對(duì)OAuth2的支持》https://www.cnblogs.com/cjsblog/p/9184173.html

        利用OAuth2實(shí)現(xiàn)單點(diǎn)登錄

        接下來,只講跟本例相關(guān)的一些配置,不講原理,不講為什么

        眾所周知,在OAuth2在有授權(quán)服務(wù)器、資源服務(wù)器、客戶端這樣幾個(gè)角色,當(dāng)我們用它來實(shí)現(xiàn)SSO的時(shí)候是不需要資源服務(wù)器這個(gè)角色的,有授權(quán)服務(wù)器和客戶端就夠了。

        授權(quán)服務(wù)器當(dāng)然是用來做認(rèn)證的,客戶端就是各個(gè)應(yīng)用系統(tǒng),我們只需要登錄成功后拿到用戶信息以及用戶所擁有的權(quán)限即可

        之前我一直認(rèn)為把那些需要權(quán)限控制的資源放到資源服務(wù)器里保護(hù)起來就可以實(shí)現(xiàn)權(quán)限控制,其實(shí)是我想錯(cuò)了,權(quán)限控制還得通過Spring Security或者自定義攔截器來做

        3.1. Spring Security 、OAuth2、JWT、SSO

        在本例中,一定要分清楚這幾個(gè)的作用

        首先,SSO是一種思想,或者說是一種解決方案,是抽象的,我們要做的就是按照它的這種思想去實(shí)現(xiàn)它

        其次,OAuth2是用來允許用戶授權(quán)第三方應(yīng)用訪問他在另一個(gè)服務(wù)器上的資源的一種協(xié)議,它不是用來做單點(diǎn)登錄的,但我們可以利用它來實(shí)現(xiàn)單點(diǎn)登錄。在本例實(shí)現(xiàn)SSO的過程中,受保護(hù)的資源就是用戶的信息(包括,用戶的基本信息,以及用戶所具有的權(quán)限),而我們想要訪問這這一資源就需要用戶登錄并授權(quán),OAuth2服務(wù)端負(fù)責(zé)令牌的發(fā)放等操作,這令牌的生成我們采用JWT,也就是說JWT是用來承載用戶的Access_Token的

        最后,Spring Security是用于安全訪問的,這里我們我們用來做訪問權(quán)限控制

        認(rèn)證服務(wù)器配置

        4.1. Maven依賴

        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.1.3.RELEASE</version>
                <relativePath/> <!-- lookup parent from repository -->
            </parent>
            <groupId>com.cjs.sso</groupId>
            <artifactId>oauth2-sso-auth-server</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <name>oauth2-sso-auth-server</name>

            <properties>
                <java.version>1.8</java.version>
            </properties>

            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-jpa</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-redis</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-security</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.security.oauth.boot</groupId>
                    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                    <version>2.1.3.RELEASE</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.session</groupId>
                    <artifactId>spring-session-data-redis</artifactId>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <optional>true</optional>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.security</groupId>
                    <artifactId>spring-security-test</artifactId>
                    <scope>test</scope>
                </dependency>

                <dependency>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                    <version>3.8.1</version>
                </dependency>
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>fastjson</artifactId>
                    <version>1.2.56</version>
                </dependency>

            </dependencies>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>

        </project>

        這里面最重要的依賴是:spring-security-oauth2-autoconfigure

        4.2. application.yml

        spring:
          datasource:
            url: jdbc:mysql://localhost:3306/permission
            username: root
            password: 123456
            driver-class-name: com.mysql.jdbc.Driver
          jpa:
            show-sql: true
          session:
            store-type: redis
          redis:
            host: 127.0.0.1
            password: 123456
            port: 6379
        server:
          port: 8080

        4.3. AuthorizationServerConfig(重要)

        package com.cjs.sso.config;

        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.context.annotation.Primary;
        import org.springframework.security.core.token.DefaultToken;
        import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
        import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
        import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
        import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
        import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
        import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
        import org.springframework.security.oauth2.provider.token.TokenStore;
        import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
        import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

        import javax.sql.DataSource;

        /**
         * @author ChengJianSheng
         * @date 2019-02-11
         */
        @Configuration
        @EnableAuthorizationServer
        public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

            @Autowired
            private DataSource dataSource;

            @Override
            public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
                security.allowFormAuthenticationForClients();
                security.tokenKeyAccess("isAuthenticated()");
            }

            @Override
            public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                clients.jdbc(dataSource);
            }

            @Override
            public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
                endpoints.accessTokenConverter(jwtAccessTokenConverter());
                endpoints.tokenStore(jwtTokenStore());
        //        endpoints.tokenServices(defaultTokenServices());
            }

            /*@Primary
            @Bean
            public DefaultTokenServices defaultTokenServices() {
                DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
                defaultTokenServices.setTokenStore(jwtTokenStore());
                defaultTokenServices.setSupportRefreshToken(true);
                return defaultTokenServices;
            }*/

            @Bean
            public JwtTokenStore jwtTokenStore() {
                return new JwtTokenStore(jwtAccessTokenConverter());
            }

            @Bean
            public JwtAccessTokenConverter jwtAccessTokenConverter() {
                JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
                jwtAccessTokenConverter.setSigningKey("cjs");   //  Sets the JWT signing key
                return jwtAccessTokenConverter;
            }

        }

        說明:

        1. 別忘了**@EnableAuthorizationServer**
        2. Token存儲(chǔ)采用的是JWT
        3. 客戶端以及登錄用戶這些配置存儲(chǔ)在數(shù)據(jù)庫,為了減少數(shù)據(jù)庫的查詢次數(shù),可以從數(shù)據(jù)庫讀出來以后再放到內(nèi)存中

        4.4. WebSecurityConfig(重要)

        package com.cjs.sso.config;

        import com.cjs.sso.service.MyUserDetailsService;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
        import org.springframework.security.config.annotation.web.builders.HttpSecurity;
        import org.springframework.security.config.annotation.web.builders.WebSecurity;
        import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
        import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
        import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
        import org.springframework.security.crypto.password.PasswordEncoder;

        /**
         * @author ChengJianSheng
         * @date 2019-02-11
         */
        @Configuration
        @EnableWebSecurity
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

            @Autowired
            private MyUserDetailsService userDetailsService;

            @Override
            protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
            }

            @Override
            public void configure(WebSecurity web) throws Exception {
                web.ignoring().antMatchers("/assets/**""/css/**""/images/**");
            }

            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.formLogin()
                        .loginPage("/login")
                        .and()
                        .authorizeRequests()
                        .antMatchers("/login").permitAll()
                        .anyRequest()
                        .authenticated()
                        .and().csrf().disable().cors();
            }

            @Bean
            public PasswordEncoder passwordEncoder() {
                return new BCryptPasswordEncoder();
            }

        }

        4.5. 自定義登錄頁面(一般來講都是要自定義的)

        package com.cjs.sso.controller;

        import org.springframework.stereotype.Controller;
        import org.springframework.web.bind.annotation.GetMapping;

        /**
         * @author ChengJianSheng
         * @date 2019-02-12
         */
        @Controller
        public class LoginController {

            @GetMapping("/login")
            public String login() {
                return "login";
            }

            @GetMapping("/")
            public String index() {
                return "index";
            }

        }

        自定義登錄頁面的時(shí)候,只需要準(zhǔn)備一個(gè)登錄頁面,然后寫個(gè)Controller令其可以訪問到即可,登錄頁面表單提交的時(shí)候method一定要是post,最重要的時(shí)候action要跟訪問登錄頁面的url一樣

        千萬記住了,訪問登錄頁面的時(shí)候是GET請(qǐng)求,表單提交的時(shí)候是POST請(qǐng)求,其它的就不用管了

        <!DOCTYPE html>
        <html xmlns:th="http://www.thymeleaf.org">
        <head>
            <meta charset="utf-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <title>Ela Admin - HTML5 Admin Template</title>
            <meta name="description" content="Ela Admin - HTML5 Admin Template">
            <meta name="viewport" content="width=device-width, initial-scale=1">

            <link type="text/css" rel="stylesheet" th:href="@{/assets/css/normalize.css}">
            <link type="text/css" rel="stylesheet" th:href="@{/assets/bootstrap-4.3.1-dist/css/bootstrap.min.css}">
            <link type="text/css" rel="stylesheet" th:href="@{/assets/css/font-awesome.min.css}">
            <link type="text/css" rel="stylesheet" th:href="@{/assets/css/style.css}">

        </head>
        <body class="bg-dark">

        <div class="sufee-login d-flex align-content-center flex-wrap">
            <div class="container">
                <div class="login-content">
                    <div class="login-logo">
                        <h1 style="color: #57bf95;">歡迎來到王者榮耀</h1>
                    </div>
                    <div class="login-form">
                        <form th:action="@{/login}" method="post">
                            <div class="form-group">
                                <label>Username</label>
                                <input type="text" class="form-control" name="username" placeholder="Username">
                            </div>
                            <div class="form-group">
                                <label>Password</label>
                                <input type="password" class="form-control" name="password" placeholder="Password">
                            </div>
                            <div class="checkbox">
                                <label>
                                    <input type="checkbox"> Remember Me
                                </label>
                                <label class="pull-right">
                                    <a href="#">Forgotten Password?</a>
                                </label>
                            </div>
                            <button type="submit" class="btn btn-success btn-flat m-b-30 m-t-30" style="font-size: 18px;">登錄</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>


        <script type="text/javascript" th:src="@{/assets/js/jquery-2.1.4.min.js}"></script>
        <script type="text/javascript" th:src="@{/assets/bootstrap-4.3.1-dist/js/bootstrap.min.js}"></script>
        <script type="text/javascript" th:src="@{/assets/js/main.js}"></script>

        </body>
        </html>

        4.6. 定義客戶端

        img
        img

        4.7. 加載用戶

        登錄賬戶

        package com.cjs.sso.domain;

        import lombok.Data;
        import org.springframework.security.core.GrantedAuthority;
        import org.springframework.security.core.userdetails.User;

        import java.util.Collection;

        /**
         * 大部分時(shí)候直接用User即可不必?cái)U(kuò)展
         * @author ChengJianSheng
         * @date 2019-02-11
         */
        @Data
        public class MyUser extends User {

            private Integer departmentId;   //  舉個(gè)例子,部門ID

            private String mobile;  //  舉個(gè)例子,假設(shè)我們想增加一個(gè)字段,這里我們?cè)黾右粋€(gè)mobile表示手機(jī)號(hào)

            public MyUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
                super(username, password, authorities);
            }

            public MyUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
                super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
            }
        }

        加載登錄賬戶

        package com.cjs.sso.service;

        import com.alibaba.fastjson.JSON;
        import com.cjs.sso.domain.MyUser;
        import com.cjs.sso.entity.SysPermission;
        import com.cjs.sso.entity.SysUser;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.security.core.authority.SimpleGrantedAuthority;
        import org.springframework.security.core.userdetails.UserDetails;
        import org.springframework.security.core.userdetails.UserDetailsService;
        import org.springframework.security.core.userdetails.UsernameNotFoundException;
        import org.springframework.security.crypto.password.PasswordEncoder;
        import org.springframework.stereotype.Service;
        import org.springframework.util.CollectionUtils;

        import java.util.ArrayList;
        import java.util.List;

        /**
         * @author ChengJianSheng
         * @date 2019-02-11
         */
        @Slf4j
        @Service
        public class MyUserDetailsService implements UserDetailsService {

            @Autowired
            private PasswordEncoder passwordEncoder;

            @Autowired
            private UserService userService;

            @Autowired
            private PermissionService permissionService;

            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                SysUser sysUser = userService.getByUsername(username);
                if (null == sysUser) {
                    log.warn("用戶{}不存在", username);
                    throw new UsernameNotFoundException(username);
                }
                List<SysPermission> permissionList = permissionService.findByUserId(sysUser.getId());
                List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
                if (!CollectionUtils.isEmpty(permissionList)) {
                    for (SysPermission sysPermission : permissionList) {
                        authorityList.add(new SimpleGrantedAuthority(sysPermission.getCode()));
                    }
                }

                MyUser myUser = new MyUser(sysUser.getUsername(), passwordEncoder.encode(sysUser.getPassword()), authorityList);

                log.info("登錄成功!用戶: {}", JSON.toJSONString(myUser));

                return myUser;
            }
        }

        4.8. 驗(yàn)證

        img

        當(dāng)我們看到這個(gè)界面的時(shí)候,表示認(rèn)證服務(wù)器配置完成

        兩個(gè)客戶端

        5.1. Maven依賴

        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.1.3.RELEASE</version>
                <relativePath/> <!-- lookup parent from repository -->
            </parent>
            <groupId>com.cjs.sso</groupId>
            <artifactId>oauth2-sso-client-member</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <name>oauth2-sso-client-member</name>
            <description>Demo project for Spring Boot</description>

            <properties>
                <java.version>1.8</java.version>
            </properties>

            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-jpa</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-oauth2-client</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-security</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.security.oauth.boot</groupId>
                    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                    <version>2.1.3.RELEASE</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.thymeleaf.extras</groupId>
                    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
                    <version>3.0.4.RELEASE</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>

                <dependency>
                    <groupId>com.h2database</groupId>
                    <artifactId>h2</artifactId>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <optional>true</optional>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.security</groupId>
                    <artifactId>spring-security-test</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>

        </project>

        5.2. application.yml

        server:
          port: 8082
          servlet:
            context-path: /memberSystem
        security:
          oauth2:
            client:
              client-id: UserManagement
              client-secret: user123
              access-token-uri: http://localhost:8080/oauth/token
              user-authorization-uri: http://localhost:8080/oauth/authorize
            resource:
              jwt:
                key-uri: http://localhost:8080/oauth/token_key
        img

        這里context-path不要設(shè)成/,不然重定向獲取code的時(shí)候回被攔截

        5.3. WebSecurityConfig

        package com.cjs.example.config;

        import com.cjs.example.util.EnvironmentUtils;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.security.config.annotation.web.builders.HttpSecurity;
        import org.springframework.security.config.annotation.web.builders.WebSecurity;
        import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


        /**
         * @author ChengJianSheng
         * @date 2019-03-03
         */
        @EnableOAuth2Sso
        @Configuration
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

            @Autowired
            private EnvironmentUtils environmentUtils;

            @Override
            public void configure(WebSecurity web) throws Exception {
                web.ignoring().antMatchers("/bootstrap/**");
            }

            @Override
            protected void configure(HttpSecurity http) throws Exception {
                if ("local".equals(environmentUtils.getActiveProfile())) {
                    http.authorizeRequests().anyRequest().permitAll();
                }else {
                    http.logout().logoutSuccessUrl("http://localhost:8080/logout")
                            .and()
                            .authorizeRequests()
                            .anyRequest().authenticated()
                            .and()
                            .csrf().disable();
                }
            }
        }

        說明:

        1. 最重要的注解是@EnableOAuth2Sso
        2. 權(quán)限控制這里采用Spring Security方法級(jí)別的訪問控制,結(jié)合Thymeleaf可以很容易做權(quán)限控制
        3. 順便多提一句,如果是前后端分離的話,前端需求加載用戶的權(quán)限,然后判斷應(yīng)該顯示那些按鈕那些菜單

        5.4. MemberController

        package com.cjs.example.controller;

        import org.springframework.security.access.prepost.PreAuthorize;
        import org.springframework.security.core.Authentication;
        import org.springframework.stereotype.Controller;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PostMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.ResponseBody;

        import java.security.Principal;

        /**
         * @author ChengJianSheng
         * @date 2019-03-03
         */
        @Controller
        @RequestMapping("/member")
        public class MemberController {

            @GetMapping("/list")
            public String list() {

                return "member/list";
            }

            @GetMapping("/info")
            @ResponseBody
            public Principal info(Principal principal) {
                return principal;
            }

            @GetMapping("/me")
            @ResponseBody
            public Authentication me(Authentication authentication) {
                return authentication;
            }

            @PreAuthorize("hasAuthority('member:save')")
            @ResponseBody
            @PostMapping("/add")
            public String add() {

                return "add";
            }

            @PreAuthorize("hasAuthority('member:detail')")
            @ResponseBody
            @GetMapping("/detail")
            public String detail() {
                return "detail";
            }
        }

        5.5. Order項(xiàng)目跟它是一樣的

        server:
          port: 8083
          servlet:
            context-path: /orderSystem
        security:
          oauth2:
            client:
              client-id: OrderManagement
              client-secret: order123
              access-token-uri: http://localhost:8080/oauth/token
              user-authorization-uri: http://localhost:8080/oauth/authorize
            resource:
              jwt:
                key-uri: http://localhost:8080/oauth/token_key

        5.6. 關(guān)于退出

        退出就是清空用于與SSO客戶端建立的所有的會(huì)話,簡單的來說就是使所有端點(diǎn)的Session失效,如果想做得更好的話可以令Token失效,但是由于我們用的JWT,故而撤銷Token就不是那么容易,關(guān)于這一點(diǎn),在官網(wǎng)上也有提到:

        img

        本例中采用的方式是在退出的時(shí)候先退出業(yè)務(wù)服務(wù)器,成功以后再回調(diào)認(rèn)證服務(wù)器,但是這樣有一個(gè)問題,就是需要主動(dòng)依次調(diào)用各個(gè)業(yè)務(wù)服務(wù)器的logout

        工程結(jié)構(gòu)

        img

        附上源碼:https://github.com/chengjiansheng/cjs-oauth2-sso-demo.git

        1. 面試官問:前后端分離項(xiàng)目,有什么優(yōu)缺點(diǎn)?

        2. 字節(jié)一面:如何從 100 億 URL 中找出相同的 URL?

        3. Spring Boot 快速整合 Mybatis-Plus 入門教程 !解放生產(chǎn)力 !

        4. 大白話說清楚 Java 中的 this 和 super 關(guān)鍵字!

        最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

        獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

        文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

        謝謝支持喲 (*^__^*)

        瀏覽 82
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            特黄AAAAAAAAA级毛片厂 | 女人下部隐私扒开图片无遮挡 | 亚洲福利影院 | 狼友视频主页 | 亚洲狠狠 | 黄片av在线免费观看 | 亚洲AV成人无码网站色美阁 | 国产成人婬片A片免费V8 | 亚洲高清无码在线播放 | 国产精品一二三产区m553小说 |