zoukankan      html  css  js  c++  java
  • SpringSecurity总结

    图片如果太小可以右键在新标签打开或者按住 ctrl+鼠标滑轮调整页面尺寸调整。

    基础

    核心

    认证与授权

    与Shiro联系

    SpringSecurity 在 SpringBoot 出现前因为配置复杂使用较少,但是在SpringBoot 出现后搭配使用开发效率大大提高。是一款重量级框架。而 Shiro 是一款轻量级框架,配置简单一些,所以如果不使用 SpringBoot,那么一般搭配 Shiro,而使用SpringBoot 就搭配 SpringSecurity。

    核心接口

    UserDetailsService

    定义了SpringSecurity 查询用户信息的接口方法,在SpringSecurity 认证时,并不是直接通过用户名密码去数据库比对,没有对应就返回,而是先通过 username 去数据库查到对应的用户信息,然后进行拼接成 SpringSecurity 内部维护的用户对象,然后由内部方法进行密码比对。而查询数据库返回用户对象的接口方法就是由 UserDetailsService 接口定义的。

    UserDetails  

    上面说到数据库查询用户信息会返回一个SpringSecurity 内部维护的用户对象。这个用户抽象类就是 UserDetails,其内部结构如下

    public interface UserDetails extends Serializable {
        // ~ Methods
        // ========================================================================================================
    
        /**
         * Returns the authorities granted to the user. Cannot return <code>null</code>.
         * 授权列表
         * @return the authorities, sorted by natural key (never <code>null</code>)
         */
        Collection<? extends GrantedAuthority> getAuthorities();
    
        /**
         * Returns the password used to authenticate the user.
         *
         * @return the password
         */
        String getPassword();
    
        /**
         * Returns the username used to authenticate the user. Cannot return <code>null</code>.
         *
         * @return the username (never <code>null</code>)
         */
        String getUsername();
    
        /**
         * Indicates whether the user's account has expired. An expired account cannot be
         * authenticated.
         * 是否过期
         * @return <code>true</code> if the user's account is valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        boolean isAccountNonExpired();
    
        /**
         * Indicates whether the user is locked or unlocked. A locked user cannot be
         * authenticated.
         * 是否锁定,如果锁定就无法验证
         * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
         */
        boolean isAccountNonLocked();
    
        /**
         * Indicates whether the user's credentials (password) has expired. Expired
         * credentials prevent authentication.
         * 用户凭证是否过期,过期的凭证会阻止身份验证
         * @return <code>true</code> if the user's credentials are valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        boolean isCredentialsNonExpired();
    
        /**
         * Indicates whether the user is enabled or disabled. A disabled user cannot be
         * authenticated.
         * 用户是启用还是禁用,无法对禁用的用户进行身份验证
         * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
         */
        boolean isEnabled();
    }

    在使用时可以让自定义用户来实现这个接口。

    PasswordEncoder

    密码接口,一般使用 BCryptPasswordEncoder 来作为默认的密码转换器。SpringSecurity 在加密时引入盐,使得加密过程是不可逆的,而加密后的字符串包含盐信息,在比较方法中会对加密后的密码进行解析,解析出盐值,然后对输入密码进行加密,比较输入密码加密后的结果是否与原密码加密后的结果一致。使用 encode 方法进行加密, matches 方法进行密码比较。如果一致返回 true。

    常用配置

    用户名密码配置

    方式一、配置文件

    方式二、配置类

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Resource
        private PasswordEncoder passwordEncoder;
    
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            String encode = passwordEncoder.encode("123");
            auth.inMemoryAuthentication().withUser("lucy").password(encode).roles("admin");
    //        super.configure(auth);
        }
    
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
    }
    View Code

     方式三、自定义配置

     因为一般项目用户名密码都是存在数据库的,所以这是最主流的。

    1、配置UserDetails,返回用户信息

    @Service("userDetailsService")
    public class MyUserDetailService implements UserDetailsService {
    
        @Resource
        private PasswordEncoder passwordEncoder;
        @Resource
        private UsersMapper usersMapper;
    
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            Users user = usersMapper.selectOne(new QueryWrapper<Users>().eq("username", s));
            if(user == null){
                throw new UsernameNotFoundException("用户名不存在!");
            }
            // 权限列表,role
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
            return new User(s, passwordEncoder.encode(user.getPassword()),auths);
        }
    
    }
    View Code

    2、添加配置类,将userDetails注册进 SpringSecurity

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Resource
        private UserDetailsService userDetailsService;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    }
    View Code

    记住我

    原理

    在登陆后会向数据库的 persistent_logins 表中插入一条记录,表结构如下

    series 是主键, 随后将 series 和 token 进行算法转换成字符串发给客户端,后面客户端会携带 Cookie ,当下次访问时后端会解析 Cookie ,解析成 series 和 token ,然后去表中匹配,验证token是否一致,以及 last_used + 存活时间是否到期,如果都满足就再以 name 走 UserDetailsService 的方法,返回用户信息。

    配置

    建表语句:

    DROP TABLE IF EXISTS `persistent_logins`;
    CREATE TABLE `persistent_logins` (
      `username` varchar(64) NOT NULL,
      `series` varchar(64) NOT NULL,
      `token` varchar(64) NOT NULL,
      `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`series`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
       @Resource
        private DataSource datasource;
    
        /**
         * 注入记住我token表的数据源
         * @return
         */
        @Bean
        public PersistentTokenRepository persistentTokenRepository(){
            JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
            jdbcTokenRepository.setDataSource(datasource);
    //        jdbcTokenRepository.setCreateTableOnStartup(true);      // 是否自动创建token数据表,如果是第一次可以勾选,后面表存在还开启就会报错
            return jdbcTokenRepository;
        }

    可以使用在配置方法中添加 ".rememberMeParameter("rem") " 配置记住我功能的name

    注意:

    1、这里的 last_used 是拒上次打开浏览器登陆开始计算的,也就是每次打开浏览器访问一次 last_used 都会刷新一次。而浏览器内部访问并不会刷新时间。

    2、退出后(退出登陆状态)会清除数据库的token数据记录,再次访问需要重新登录

    登陆成功处理器

    步骤一:增加组件

    方式一、继承实现类

    @Slf4j
    @Component
    public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Authentication authentication)
                throws ServletException, IOException {
            User user = (User) authentication.getPrincipal();       // 获取Security 内部维护的user对象
            System.out.println(user.getUsername());     // 用户名:aa
            System.out.println(user.getPassword());     // 密码,由于加密,得到的是null:null
            System.out.println(user.getAuthorities());  // 用户权限列表:[ROLE_AAA, ROLE_sale, admins, manager]
            response.sendRedirect("http://www.baidu.com");
        }
    }
    View Code

    方式二、实现底层接口

    public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    
        private String url;
    
        public MyAuthenticationSuccessHandler(String url) {
            this.url = url;
        }
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            response.sendRedirect(url);
        }
    }
    View Code

     步骤二:将组件注册进成功处理器配置中

    登陆失败处理器

    步骤一:增加组件

    方式一、实现接口

     方式二、继承实现类

     步骤二:将组件注册进失败处理器配置中

    权限认证失败处理器

    1、组件

    2、配置

    用户退出处理器

    1、组件

     2、配置

    角色权限

    访问一个需要权限或角色的页面需要先登陆,如果登陆后还是不能访问就会返回500.

    角色、权限、用户关系

    权限与角色是多对多,角色与用户也是多对多。权限指的是对某个表具体的增删改查权限,而角色是一系列权限的集合。比如管理员角色拥有对所有表增删改查的权限,普通用户角色只拥有对所有表查询的权限,而用户 admin 拥有管理员角色,用户 A 拥有普通用户的角色。

    定义权限

    在config里配置路径所需权限,在UserDetailsService里配置用户所拥有的权限。

    1、hasAuthority 是与关系,如果在config里配置了多个权限,如”admin,manager”,那么在UserDetailsService也必须对用户配置两个角色权限才可以访问

    2、hasAnyAuthority 是或关系,如果在 config里配置了多个权限,如”admin,manager”,那么在UserDetailsService只需要对用户配置一个权限就可以访问

    定义角色

    角色在 UserDetailsService 实现类中配置需要加 "ROLE_" 前缀

    而hasRole 和hasAnyRole 对应权限里的hasAuthority 和hasAnyAuthority,是与和或的关系。

    Access 来定义权限、角色

    上面的hasRole、hasAuthority 底层都是使用 access 来实现的,所以我们还可以通过底层的access 方法来主直接定义权限、角色。

    那么 config 里配置就是如下:

    自定义 Access 校验规则

    1、组件

    2、配置

    基于 IP 来限制

    这样的话只能接收来自 127.0.0.1 的请求。

    定义角色注解

    @Secured单个””里不支持使用,隔开,也就是不支持与关系。如果要配置多个或关系,可以使用{}, 在UserDetailsService里只要配置一个就可以访问。

    并且只支持定义角色,不支持定义权限,也就是Secured里必须是ROLE_开头

    定义角色、权限注解

    可以定义角色、也可以定义权限

    如果用户拥有的角色是abc,那么在这里可以配置hasRole(‘abc’),也可以配置hasRole(‘ROLE_abc’),而使用config配置类配置则不可以,会报错。而大小写则和配置类一样会区分

    先执行后校验注解

    可以用于记录访问日志

    对返回和传入数据过滤注解

     

    CSRF

    CSRF 是为了防止用户在开启记住登陆后,其他非法用户截取到登陆用户的 Cookie ,登陆其他用户进行非法操作。

    默认是开启的,开启后用户登录时,系统发放一个CsrfToken值(key是 _csrf,value是token值),用户携带该CsrfToken值与用户名、密码等参数完成登录。系统记录该会话的 CsrfToken 值,之后在用户的任何请求中,都必须带上该CsrfToken值,并由系统进行校验。

    配置:

    相关依赖:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!--对Thymeleaf添加Spring Security标签支持-->
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            </dependency>

    开启 CSRF 时配置类不能配置 loginProcessingUrl 和 defaultSuccessUrl 。会影响登陆跳转逻辑。

    其他配置

    1、如果配置了登陆的URL(也就是loginProcessingUrl),那么自定义Controller里处理的登陆请求就会用不到,走的是SpringSecurity内部的验证方法。

    2、anyRequest()必须配置在所有的antMatches后面,也就是笼统的权限配置必须放在其他权限的最后

    3、and()是用于连接多个http配置。     

    4、在开发时需要添加@EnableWebSecurity注解,这个注解会自动配置安全认证策略和认证信息。

    整合OAuth2

    关于 OAuth2 与 JWT 可以移步 浅谈常见的认证机制 。

    基础依赖

            <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> 

    基础配置

    因为 OAuth2 涉及到资源服务器和授权服务器,所以除了配置 SpringSecurity ,还需要配置资源服务器和授权服务器。

    1、SpringSecurity配置:

    @EnableWebSecurity
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().permitAll()
                    .and()
                    .csrf().disable();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    }
    View Code

    2、授权服务器配置:定义 app_id、app_secret,以及重定向地址,授权范围等

     这里直接贴下包含下面整合 redis 存储、JWT、SSO总的配置,根据图片需要进行选择

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
        @Resource
        private PasswordEncoder passwordEncoder;
        @Resource
        private AuthenticationManager authenticationManager;
        @Resource
        private UserService userDetailsService;
    
        @Resource
        private TokenStore jwtTokenStore;       // 使用jwt存储(因为jwt是无状态的,所以并不会持久化)
    //    @Resource
    //    private TokenStore redisTokenStore;       // 使用redis存储
        @Resource
        private JwtAccessTokenConverter jwtAccessTokenConverter;
        @Resource
        private JwtTokenEnhancer jwtTokenEnhancer;
        /**
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            // 设置 JWT 增强内容
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            List<TokenEnhancer> delegates = new ArrayList<>();
            delegates.add(jwtTokenEnhancer);
            delegates.add(jwtAccessTokenConverter);
            tokenEnhancerChain.setTokenEnhancers(delegates);
    
            endpoints.authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService)                 // 密码模式需要配置的
                    .tokenStore(jwtTokenStore)
                    .tokenEnhancer(tokenEnhancerChain)            // 增加额外数据
                    .accessTokenConverter(jwtAccessTokenConverter);     // 使用jwt来代替默认的令牌
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()      // 放入内存
                    .withClient("client")       // 客户端ID
                    .secret(passwordEncoder.encode("112233"))               // 密钥
                    // 重定向地址,这里整合SSO设置为客户端的login页面是因为SpringSecurity默认登陆页面的URL就是login,在客户端通过授权服务器通过后
                    // 携带令牌重定向到客户端8081的login页面,自动解析令牌完成登陆。
                    .redirectUris("http://www.baidu.com")
                    .scopes("all")      // 授权范围
                    .autoApprove(true)          // 开启自动授权(不需要进入授权页面手动选择授权)
                    .accessTokenValiditySeconds(60)         // 过期时间,单位s
                    .refreshTokenValiditySeconds(86400)         // 刷新令牌过期时间
                    .authorizedGrantTypes("authorization_code","password","refresh_token");        //授权类型:
                                                                                        // authorization_code:授权码模式
                                                                                        // password:密码模式
                                                                                        // refresh_token:支持刷新令牌
        }
    
    
        /**
         * 配置单点登陆
         * @param security
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.tokenKeyAccess("isAuthenticated()");
        }
    }
    View Code

    3、资源服务器配置:定义资源服务器资源权限角色配置。

     4、其他:userDetailsService 配置

    @Service("userDetailsService")
    public class UserService implements UserDetailsService {
    
        @Resource
        private PasswordEncoder passwordEncoder;
    
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            // 权限列表,role
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin1");
            return new User(s, passwordEncoder.encode("123456"),auths);
        }
    }
    View Code

    自定义用户实体类 user ,权限属性全部设为 true。

    public class User implements UserDetails {
    
        private String username;
        private String password;
        private List<GrantedAuthority> authorities;
    
        public User(String username, String password, List<GrantedAuthority> authorities) {
            this.username = username;
            this.password = password;
            this.authorities = authorities;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }
    
        @Override
        public String getPassword() {
            return password;
        }
    
        @Override
        public String getUsername() {
            return username;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    View Code

    资源服务器的资源Controller

    同样贴上完整代码,根据图片需要选择

    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/getCurrentUser")
        public Object getCurrentUser(HttpServletRequest request,Authentication authentication){
            String authorization = request.getHeader("Authorization");
            String token = authorization.substring(authorization.lastIndexOf("bearer") + 7);
            return Jwts.parser()
                    .setSigningKey("test_key".getBytes(StandardCharsets.UTF_8))          // 密钥必须和加密所用的一致
                    .parseClaimsJws(token)
                    .getBody();
    //        return authentication.getPrincipal();
        }
    }
    View Code

    授权码模式

    在上面的授权服务器配置中,已将授权类型设为 授权码模式,所以直接使用上面的配置。

    验证

    1、获取授权码

    访问 http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://www.baidu.com&scope=all ,在登陆成功后(因为走的是上面 userDetailsService 的方法,所以用户名任意,密码123456就通过登陆),会重定向授权服务器配置中配置好的 http://www.baidu.com 。并且携带授权服务器返回的授权码 code。

    2、获取授权令牌

    接下来就可以再次访问 localhost:8080/oauth/token 携带授权码及其他数据来向授权服务器获取授权令牌。

     3、通过令牌访问资源服务器的资源,访问资源服务器上资源的 URL,并携带授权令牌。

    密码模式

    密码模式因为是通过密码直接获取授权令牌,所以不需要先获取授权码,同时需要设置自定义的 userDetailsService 实现类,以及 authenticationManager 组件

    1、ServurityConfig里增加配置:

     2、授权服务器增加配置:

    这样配置是同时支持授权码模式与密码模式

    验证 

    通过密码获取授权令牌

    访问资源服务器的资源则和授权码模式验证一样。

     

    整合 redis 将令牌存入 redis

    1、引入依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>    

    2、注册 redis 的 tokenStore 组件进容器

    @Configuration
    public class RedisConfig {
    
        @Resource
        private RedisConnectionFactory redisConnectionFactory;
    
        @Bean
        public TokenStore redisTokenStore(){
            return new RedisTokenStore(redisConnectionFactory);
        }
    }
    View Code

    3、在授权服务器里注册 tokenStore

    4、在配置文件里配置 redis 地址密码等。

    使用 JWT 作为令牌

    1、增加依赖

            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.0</version>
            </dependency>    

    2、从容器中移除 redis 的 tokenStore 组件,同时想容器中加入 jwt 的 tokenStore 组件,并且配置 jwt 的转换器

    完整代码,根据图片需要自取

    @Configuration
    public class JwtTokenStoreConfig {
    
        @Resource
        private JwtAccessTokenConverter jwtAccessTokenConverter;
    
        // 保存 token的组件
        @Bean
        public TokenStore jwtTokenStore(){
            return new JwtTokenStore(jwtAccessTokenConverter);
        }
    
        // Jwt 转换器,用于将jwt转换成 OAuth2的令牌
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
            // 设置jwt密匙
            jwtAccessTokenConverter.setSigningKey("test_key");
            return jwtAccessTokenConverter;
        }
    
        // 配置Jwt的附加信息
        @Bean
        public JwtTokenEnhancer jwtTokenEnhancer(){
            return new JwtTokenEnhancer();
        }
    
    }
    View Code

    3、注册进授权服务器

    JWT 增加额外信息

    1、增加 Jwt 附加信息组件并注册进容器

    public class JwtTokenEnhancer implements TokenEnhancer {
    
    
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("enhance", "enhancer info");
            ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(map);
            return oAuth2AccessToken;
        }
    }
    View Code

    2、在授权服务器里配置 jwt 附加信息组件

    3、验证,修改资源服务器资源返回的信息 

    设置过期时间和刷新令牌

    在授权服务器里增加配置:

    在60s后token令牌(access_token)失效后,可以使用刷新令牌重新获取新的令牌,新的令牌过期时间也是60s。

    因为密码模式不支持刷新令牌,所以通过授权码模式使用刷新令牌来获取新的令牌

    通过刷新令牌获取令牌

    整合SSO(单点登陆)

    整合 SSO 后验证的原理就成了下面

     各个服务模块都使用同一个授权服务器,也就是图中的认证中心,在第一次访问模块A时会去跳转到授权服务器进行验证,如果通过,那么就会返回给前端一个 token 令牌,以后在访问A或B时,都会携带这个令牌,而验证时都是通过同一个授权服务器验证,所以都会解析通过,进而访问对应的资源。

    1、引入依赖

            <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>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.0</version>
            </dependency>

    2、新建一个模块,配置 SSO 访问授权服务器的地址

    server.port=8081
    #防止Cookie冲突,冲突会导致登陆验证不通过
    server.servlet.session.cookie.name=OAUTH2-CLIENT-SESSIONID1
    #授权服务器地址
    oauth2-server-url: http://localhost:8080
    #与授权服务器对应的配置
    security.oauth2.client.client-id=client
    security.oauth2.client.client-secret=112233
    #获取授权码地址
    security.oauth2.client.user-authorization-uri=${oauth2-server-url}/oauth/authorize
    #获取令牌地址
    security.oauth2.client.access-token-uri=${oauth2-server-url}/oauth/token
    #获取jwt令牌地址
    security.oauth2.resource.jwt.key-uri=${oauth2-server-url}/oauth/token_key
    View Code

    3、增加 SSO 模块的资源

    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/getCurrentUser")
        public Object getCurrentUser(HttpServletRequest request,Authentication authentication){
            return authentication;
        }
    }
    View Code

    4、主程序开启 OAuth2 自动配置

    5、在授权服务器的配置增加配置

    随后访问客户端资源 http://localhost:8081/user/getCurrentUser 就会先跳转到 http://localhost:8080/login ,也就是授权服务器进行授权验证,通过后经重定向回到 http://localhost:8081/login ,也就是客户端的登陆页面,并且携带授权服务器提供的jwt令牌,所以会自动解析通过验证,最后再访问客户端的资源

  • 相关阅读:
    php注释规范
    Jquery元素选取、常用方法
    pdo 添加数据
    pdo 访问数据库
    session / cookie 区别与应用
    注册审核
    分页 --条件查询再分页
    Python 第二十九章 socket通信
    Python 第二十八章 网络初识+五层协议+三次握手四次挥手
    Python 第二十六章 面向对象 元类+反射+双下方法
  • 原文地址:https://www.cnblogs.com/mengxinJ/p/14897480.html
Copyright © 2011-2022 走看看