zoukankan      html  css  js  c++  java
  • 【Spring-Security】Re14 Oauth2协议P4 整合SSO单点登陆

    创建一个SSO单点登陆的客户端工程

    需要的依赖和之前的项目基本一致:

    <?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 https://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.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>cn.zeal4j</groupId>
        <artifactId>sso-client</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sso-client</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-oauth2</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-security</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version><!--<version>Greenwich.SR2</version>-->
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    YML配置:

    server:
      port: 8081 # 防止和服务端的端口冲突
      servlet:
        session:
          cookie:
            name: 'SSO-CLIENT-SESSION-ID' # 防止COOKIE冲突
    # 授权服务器地址:
    oauth2-server-url: http://localhost:8080
    # 授权服务器的相关配置
    security:
      oauth2:
        resource:
          jwt:
            key-uri: ${oauth2-server-url}/oauth/token_key
        client:
          client-id: admin
          client-secret: 112233
          user-authorization-uri: ${oauth2-server-url}/oauth/authorize
          access-token-uri: ${oauth2-server-url}/oauth/token

    客户端启动类打上支持SSO单点登陆注解

    然后写一个简单的信息获取接口

    package cn.zeal4j.controller;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @author Administrator
     * @file IntelliJ IDEA Spring-Security-SSO-Client
     * @create 2020 09 30 0:38
     */
    @Controller
    @RequestMapping("user")
    public class UserController {
    
        /**
         * user/getCurrentUser
         * @param authentication
         * @return
         */
        @RequestMapping("getCurrentUser")
        @ResponseBody
        public Object getCurrentUser(Authentication authentication) {
            return authentication.getPrincipal();
        }
    }

    回到服务端,设置跳转的地址是客户端IP位置:

    package cn.zeal4j.configuration;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.password.PasswordEncoder;
    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.TokenEnhancer;
    import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
    import org.springframework.security.oauth2.provider.token.TokenStore;
    import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Administrator
     * @file Spring-Security + Oauth2
     * @create 2020 09 29 11:48
     * @description 授权服务器配置
     */
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Autowired
        private AuthenticationManager authenticationManager;
        @Qualifier("customUserDetailsServiceImpl")
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Qualifier("getTokenStore")
        @Autowired
        private TokenStore tokenStore;
    
        @Qualifier("getJwtAccessTokenConverter")
        @Autowired
        private JwtAccessTokenConverter jwtAccessTokenConverter;
    
        @Qualifier("getJwtTokenEnhancer")
        @Autowired
        private TokenEnhancer tokenEnhancer;
    
    //    @Qualifier("getRedisTokenStore")
    //    @Autowired
    //    private TokenStore tokenStore;
    
        /**
         * 使用密码模式需要的配置方法
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
            // - - - - - 配置JWT自定义申明增强 Starter - - - - -
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            List<TokenEnhancer> tokenEnhancerList = new ArrayList<>();
    
            tokenEnhancerList.add(tokenEnhancer);
            tokenEnhancerList.add(jwtAccessTokenConverter);
    
            tokenEnhancerChain.setTokenEnhancers(tokenEnhancerList);
            // - - - - - 配置JWT自定义申明增强 End - - - - -
    
            endpoints.
                    authenticationManager(authenticationManager).
                    userDetailsService(userDetailsService).
                    accessTokenConverter(jwtAccessTokenConverter).
                    tokenEnhancer(tokenEnhancerChain);
    //                tokenStore(tokenStore);
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.
                    inMemory().
                    withClient("admin").
                    secret(passwordEncoder.encode("112233")).
                    // accessTokenValiditySeconds(3600). // 令牌有效时间 一小时
                    // redirectUris("http://www.baidu.com"). // 授权成功的跳转
                    accessTokenValiditySeconds(3600). // 过期时间
                    refreshTokenValiditySeconds(864000).  // 刷新令牌的过期时间
                    redirectUris("http://localhost:8081/login").
                    autoApprove(true). //自动授权
                    scopes("all").  // 所有范围
                    // authorizedGrantTypes("authorization_code");     // 授权类型:授权码模式
                    authorizedGrantTypes("password", "refresh_token", "authorization_code");     // 授权类型:密码模式 追加令牌刷新,和兼容授权码模式
        }
    
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            // 密钥获取之前的身份认证,单点登陆必须配置
            security.tokenKeyAccess("isAuthenticated()");
        }
    }

    配置完成后先启动服务端,再启动客户端,注意不要同时启动,我出现了一个进程占用的情况

    两个服务都无法开启,手动杀死8080端口的进程解决了

    两边控制台显示运行成功之后,访问客户端的接口:

    http://localhost:8081/user/getCurrentUser

    结果会被重定向到服务端的登陆:

    http://localhost:8080/login

    输入用户信息登陆之后,会自动跳回到我们一开始希望访问的接口:

    直接获取authentication对象能得到完整的信息

    package cn.zeal4j.controller;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @author Administrator
     * @file IntelliJ IDEA Spring-Security-SSO-Client
     * @create 2020 09 30 0:38
     */
    @Controller
    @RequestMapping("user")
    public class UserController {
    
        /**
         * user/getCurrentUser
         * @param authentication
         * @return
         */
        @RequestMapping("getCurrentUser")
        @ResponseBody
        public Object getCurrentUser(Authentication authentication) {
            // return authentication.getPrincipal();
            return authentication;
        }
    }

    JSON数据:

    {
        "authorities": [{
            "authority": "admin"
        }],
        "details": {
            "remoteAddress": "0:0:0:0:0:0:0:1",
            "sessionId": "C7FBF0520D8CA4DF4131B9E05965B6AA",
            "tokenValue": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2MDE0MDI1NjIsImp3dC1rZXktYWFhIjoiand0LXZhbHVlLUFBQSIsImF1dGhvcml0aWVzIjpbImFkbWluIl0sImp0aSI6ImFhMjJkNmY2LWMxYzMtNDg0ZS1iZjI5LTYzZTg1Y2ZlZGY4YSIsImp3dC1rZXktYmJiIjoiand0LXZhbHVlLUJCQiIsImNsaWVudF9pZCI6ImFkbWluIiwiand0LWtleS1jY2MiOiJqd3QtdmFsdWUtQ0NDIn0.LG-D88n-hNoVOG1hrlpwEs-64jA-T2TPdlRi0cram-w",
            "tokenType": "bearer",
            "decodedDetails": null
        },
        "authenticated": true,
        "userAuthentication": {
            "authorities": [{
                "authority": "admin"
            }],
            "details": null,
            "authenticated": true,
            "principal": "admin",
            "credentials": "N/A",
            "name": "admin"
        },
        "principal": "admin",
        "credentials": "",
        "clientOnly": false,
        "oauth2Request": {
            "clientId": "admin",
            "scope": ["all"],
            "requestParameters": {
                "client_id": "admin"
            },
            "resourceIds": [],
            "authorities": [],
            "approved": true,
            "refresh": false,
            "redirectUri": null,
            "responseTypes": [],
            "extensions": {},
            "grantType": null,
            "refreshTokenRequest": null
        },
        "name": "admin"
    }

    代码笔记已上传到Gitee仓库中,需要的自取:

    https://gitee.com/daizhizhou/spring-security-tutorial
  • 相关阅读:
    yii框架原生代码
    分库分表
    get和post的区别
    echo print() print_r() var_dump()的区别
    cookie 和session 的区别
    memcached 常用命令及使用说明
    解决高并发
    C# 使用NLog记录日志
    CREATE DATABASE permission denied in database 'master'.
    No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • 原文地址:https://www.cnblogs.com/mindzone/p/13752642.html
Copyright © 2011-2022 走看看