前言

后面咱们曾经实现了生成access_token,上面咱们看如何把access_token转换成jwt的形式给到第三方。

调整

保留策略改成JWT即可
AuthServerConfig:OAuth2的受权服务:次要作用是OAuth2的客户端进行认证与受权

package com.baba.security.auth2.auth;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.UserDetailsService;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 javax.sql.DataSource;import java.util.ArrayList;import java.util.List;/** * OAuth2的受权服务:次要作用是OAuth2的客户端进行认证与受权 * @Author wulongbo * @Date 2021/11/26 9:59 * @Version 1.0 */@Configuration@EnableAuthorizationServerpublic class AuthServerConfig extends AuthorizationServerConfigurerAdapter {    @Autowired    @Qualifier("memberUserDetailsService")    public UserDetailsService userDetailsService;    @Autowired    private DataSource dataSource;    @Autowired    private AuthenticationManager authenticationManager;    @Autowired    private TokenStore jwtTokenStore;    @Autowired    private JwtAccessTokenConverter jwtAccessTokenConverter;    @Autowired    private TokenEnhancer jwtTokenEnhancer;    /**     * 配置OAuth2的客户端信息:clientId、client_secret、authorization_type、redirect_url等。     * 理论保留在数据库中     * @param clients     * @throws Exception     */    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.jdbc(dataSource);    }    /**     * 1.减少jwt 加强模式     * 2.调用userDetailsService实现UserDetailsService接口,对客户端信息进行认证与受权     * @param endpoints     * @throws Exception     */    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        /**         * jwt 加强模式         * 对令牌的加强操作就在enhance办法中         * 上面在配置类中,将TokenEnhancer和JwtAccessConverter加到一个enhancerChain中         *         * 艰深点讲它做了两件事:         * 给JWT令牌中设置附加信息和jti:jwt的惟一身份标识,次要用来作为一次性token,从而回避重放攻打         * 判断申请中是否有refreshToken,如果有,就从新设置refreshToken并退出附加信息         */        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();        List<TokenEnhancer> enhancerList = new ArrayList<TokenEnhancer>();        enhancerList.add(jwtTokenEnhancer);        enhancerList.add(jwtAccessTokenConverter);        enhancerChain.setTokenEnhancers(enhancerList); //将自定义Enhancer退出EnhancerChain的delegates数组中        endpoints.tokenStore(jwtTokenStore)                .userDetailsService(userDetailsService)                /**                 * 反对 password 模式                 */                .authenticationManager(authenticationManager)                .tokenEnhancer(enhancerChain)                .accessTokenConverter(jwtAccessTokenConverter);    }    @Override    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {        security                .tokenKeyAccess("permitAll()")//                .checkTokenAccess("isAuthenticated()")                //解决/oauth/check_token无法访问的问题                .checkTokenAccess("permitAll()")                .allowFormAuthenticationForClients();    }}

ResServerConfig:基于OAuth2的资源服务配置类

package com.baba.security.auth2.auth;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.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.RemoteTokenServices;import org.springframework.security.oauth2.provider.token.TokenStore;/** * ********在理论我的项目中此资源服务能够独自提取到资源服务项目中应用******** * <p> * OAuth2的资源服务配置类(次要作用是配置资源受爱护的OAuth2策略) * 注:技术架构通常上将用户与客户端的认证受权服务设计在一个子系统(工程)中,而资源服务设计为另一个子系统(工程) * * @Author wulongbo * @Date 2021/11/26 10:01 * @Version 1.0 */@Configuration@EnableResourceServer@EnableGlobalMethodSecurity(prePostEnabled = true)public class ResServerConfig extends ResourceServerConfigurerAdapter {    @Autowired    private TokenStore jwtTokenStore;    /**     * 同认证受权服务配置jwtTokenStore - 独自剥离服务须要开启正文     * @return     *///    @Bean//    public TokenStore jwtTokenStore() {//        return new JwtTokenStore(jwtAccessTokenConverter());//    }    /**     * 同认证受权服务配置jwtAccessTokenConverter  - 独自剥离服务须要开启正文     * 须要和认证受权服务设置的jwt签名雷同: "demo"     *     * @return     *///    @Bean//    public JwtAccessTokenConverter jwtAccessTokenConverter() {//        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();//        accessTokenConverter.setSigningKey(Oauth2Constant.JWT_SIGNING_KEY);//        accessTokenConverter.setVerifierKey(Oauth2Constant.JWT_SIGNING_KEY);//        return accessTokenConverter;//    }    @Override    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {        resources.tokenStore(jwtTokenStore);    }    /**     * 配置受OAuth2爱护的URL资源。     * 留神:必须配置sessionManagement(),否则拜访受护资源申请不会被OAuth2的拦截器     * ClientCredentialsTokenEndpointFilter与OAuth2AuthenticationProcessingFilter拦挡,     * 也就是说,没有配置的话,资源没有受到OAuth2的爱护。     *     * @param http     * @throws Exception     */    @Override    public void configure(HttpSecurity http) throws Exception {        /*         留神:         1、必须先加上:.requestMatchers().antMatchers(...),示意对资源进行爱护,也就是说,在拜访前要进行OAuth认证。         2、接着:拜访受爱护的资源时,要具备哪里权限。         ------------------------------------         否则,申请只是被Security的拦截器拦挡,申请基本到不了OAuth2的拦截器。         ------------------------------------         requestMatchers()局部阐明:         Invoking requestMatchers() will not override previous invocations of ::         mvcMatcher(String)}, requestMatchers(), antMatcher(String), regexMatcher(String), and requestMatcher(RequestMatcher).         */        http                // Since we want the protected resources to be accessible in the UI as well we need                // session creation to be allowed (it's disabled by default in 2.0.6)                //另外,如果不设置,那么在通过浏览器拜访被爱护的任何资源时,每次是不同的SessionID,并且将每次申请的历史都记录在OAuth2Authentication的details的中                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)                .and()                .requestMatchers()                .antMatchers("/user", "/res/**","/home/**")                .and()                .authorizeRequests()                .anyRequest().authenticated();//                .antMatchers("/user", "/res/**","/home/**")//                .authenticated();    }}

SecurityConfig:其中sourceService就是后面的PermissionService革新一下,针对客户端对外的所有凋谢接口进行权限管制,所以表辨别了一下。

package com.baba.security.auth2.auth;import com.baba.security.auth2.entity.PermissionEntity;import com.baba.security.auth2.entity.Source;import com.baba.security.auth2.service.PermissionService;import com.baba.security.auth2.service.SourceService;import com.baba.security.auth2.service.impl.MemberUserDetailsService;import com.baba.security.common.utils.MD5Util;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.security.authentication.AuthenticationManager;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.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.stereotype.Component;import java.util.List;/** * 配置咱们httpBasic 登陆账号和明码 */@Component@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired    private SourceService sourceService;    @Autowired    private MemberUserDetailsService memberUserDetailsService;    /**     * 反对 password 模式(配置)     * @return     * @throws Exception     */    @Override    @Bean    public AuthenticationManager authenticationManagerBean() throws Exception {        return super.authenticationManagerBean();    }    /**     * 引入明码加密类     * @return     */    @Bean    public PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {//        auth.//                inMemoryAuthentication()//                .withUser("mayikt")//                .password(passwordEncoder().encode("654321"))//                .authorities("/*");////        auth.//                inMemoryAuthentication()//                .withUser("baidu")//                .password(passwordEncoder().encode("54321"))//                .authorities("/*");//        System.out.println("===============================");//        System.out.println(passwordEncoder().encode("123456"));//        System.out.println(new BCryptPasswordEncoder().encode("12345"));        auth.userDetailsService(memberUserDetailsService).passwordEncoder(new PasswordEncoder() {            /**             * 对明码MD5             * @param rawPassword             * @return             */            @Override            public String encode(CharSequence rawPassword) {                return MD5Util.encode((String) rawPassword);            }            /**             * rawPassword 用户输出的明码             * encodedPassword 数据库DB的明码             * @param rawPassword             * @param encodedPassword             * @return             */            @Override            public boolean matches(CharSequence rawPassword, String encodedPassword) {                String rawPass = MD5Util.encode((String) rawPassword);                boolean result = rawPass.equals(encodedPassword);                return result;            }        });    }    /**     * 配置URL拜访受权,必须配置authorizeRequests(),否则启动报错,说是没有启用security技术。     * 留神:在这里的身份进行认证与受权没有波及到OAuth的技术:当拜访要受权的URL时,申请会被DelegatingFilterProxy拦挡,     *      如果还没有受权,申请就会被重定向到登录界面。在登录胜利(身份认证并受权)后,申请被重定向至之前拜访的URL。     * @param http     * @throws Exception     */    @Override    protected void configure(HttpSecurity http) throws Exception {//        http.formLogin() //注销界面,默认是permit All//                .and()//                .authorizeRequests().antMatchers("/","/home").permitAll() //不必身份认证能够拜访//                .and()//                .authorizeRequests().anyRequest().authenticated() //其它的申请要求必须有身份认证//                .and()//                .csrf() //避免CSRF(跨站申请伪造)配置//                .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable();        Source source = new Source();        List<Source> allPermission = sourceService.findByAll(source);        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry                expressionInterceptUrlRegistry = http.authorizeRequests();        allPermission.forEach((s) -> {            expressionInterceptUrlRegistry.antMatchers(s.getUrl()).                    hasRole(s.getTag());        });        http                .formLogin()                .and()//                .authorizeRequests().antMatchers("/","/home").permitAll() //不必身份认证能够拜访//                .and()                //容许不登陆就能够拜访的办法,多个用逗号分隔                .authorizeRequests()                //跨域申请会先进行一次options申请//                .antMatchers(HttpMethod.OPTIONS).permitAll()//                .antMatchers("/","/home").permitAll() //不必身份认证能够拜访                //其余的须要受权后拜访                .antMatchers("/**").authenticated() //其它的申请要求必须有身份认证//                .anyRequest().authenticated() //其它的申请要求必须有身份认证//                // 加一句这个                .and()                .csrf().disable(); //关跨域爱护    }}

Oauth2Constant :当然签名能够改动静

package com.baba.security.auth2.constant;/** * @Author wulongbo * @Date 2021/11/26 9:56 * @Version 1.0 */public class Oauth2Constant {    /**************************************Oauth2参数配置**********************************************/    /**     * JWT_SIGNING_KEY     */    public static final String JWT_SIGNING_KEY = "jwtsigningkey";}

JWTokenEnhancer:自定义TokenEnhancer

package com.baba.security.auth2.config;import com.baba.security.auth2.entity.User;import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;import org.springframework.security.oauth2.common.OAuth2AccessToken;import org.springframework.security.oauth2.provider.OAuth2Authentication;import org.springframework.security.oauth2.provider.token.TokenEnhancer;import java.util.HashMap;import java.util.Map;/** * TokenEnhancer:在AuthorizationServerTokenServices 实现存储拜访令牌之前加强拜访令牌的策略。 * 自定义TokenEnhancer的代码:把附加信息退出oAuth2AccessToken中 * * @Author wulongbo * @Date 2021/11/26 9:58 * @Version 1.0 */public class JWTokenEnhancer implements TokenEnhancer {    /**     * 重写enhance办法,将附加信息退出oAuth2AccessToken中     *     * @param oAuth2AccessToken     * @param oAuth2Authentication     * @return     */    @Override    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {        Map<String, Object> map = new HashMap<String, Object>();        User user = (User)oAuth2Authentication.getPrincipal();        map.put("id", user.getId());        map.put("jwt-ext", "把把智能科技");        ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(map);        return oAuth2AccessToken;    }}

JwtTokenConfig:JwtTokenConfig配置类

package com.baba.security.auth2.config;import com.baba.security.auth2.constant.Oauth2Constant;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.oauth2.provider.token.TokenEnhancer;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;/** * JwtTokenConfig配置类 * 应用TokenStore将引入JwtTokenStore * * 注:Spring-Sceurity应用TokenEnhancer和JwtAccessConverter加强jwt令牌 * @author wulongbo * @date 2021-11-27 */@Configurationpublic class JwtTokenConfig {    @Bean    public TokenStore jwtTokenStore() {        return new JwtTokenStore(jwtAccessTokenConverter());    }    /**     * JwtAccessTokenConverter:TokenEnhancer的子类,帮忙程序在JWT编码的令牌值和OAuth身份验证信息之间进行转换(在两个方向上),同时充当TokenEnhancer授予令牌的工夫。     * 自定义的JwtAccessTokenConverter:把本人设置的jwt签名退出accessTokenConverter中(这里设置'demo',我的项目可将此在配置文件设置)     * @return     */    @Bean    public JwtAccessTokenConverter jwtAccessTokenConverter() {        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();//        accessTokenConverter.setVerifierKey(Oauth2Constant.JWT_SIGNING_KEY);        accessTokenConverter.setSigningKey(Oauth2Constant.JWT_SIGNING_KEY);        return accessTokenConverter;    }    /**     * 引入自定义JWTokenEnhancer:     * 自定义JWTokenEnhancer实现TokenEnhancer并重写enhance办法,将附加信息退出oAuth2AccessToken中     * @return     */    @Bean    public TokenEnhancer jwtTokenEnhancer(){        return new JWTokenEnhancer();    }}

GetSecret (获取Header以及加密后的明码)

package com.baba.security.auth2.utils;import org.apache.commons.codec.binary.Base64;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import java.nio.charset.Charset;/** * (获取Header以及加密后的明码) * @Author wulongbo * @Date 2021/11/26 10:50 * @Version 1.0 */public class GetSecret {    /**     * 对应数据库中的client_id的值     */    private static final String APP_KEY = "mayikt_appid";    /**     * 对应数据库中的client_secret的值     */    private static final String SECRET_KEY = "123456";    /**     * main办法执行程序获取到数据库中加密后的client_secret和申请头中的getHeader     * @param args     */    public static void main(String[] args){        System.out.println();        System.out.println("client_secret: "+new BCryptPasswordEncoder().encode(SECRET_KEY));        System.out.println("getHeader: "+getHeader());    }    /**     * 结构Basic Auth认证头信息     *     * @return     */    private static String getHeader() {        String auth = APP_KEY + ":" + SECRET_KEY;        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));        String authHeader = "Basic " + new String(encodedAuth);        return authHeader;    }}

pom这里不再应用cloud,应用boot的 :

<?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">    <parent>        <artifactId>zuul-auth</artifactId>        <groupId>com.babaznkj.com</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>auth2</artifactId>    <properties>        <maven.compiler.source>8</maven.compiler.source>        <maven.compiler.target>8</maven.compiler.target>    </properties>    <dependencies>        <dependency>            <groupId>com.babaznkj.com</groupId>            <artifactId>common</artifactId>        </dependency>        <!-- mysql驱动 -->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>${mysql.version}</version>        </dependency>        <!-- mybatis启动器 -->        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>${mybatis.starter.version}</version>        </dependency>        <!-- alibaba的druid数据库连接池 -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>${druid.starter.version}</version>        </dependency>        <!-- spring-boot -->        <!-- 此oauth2依赖为spingcloud依赖,在springboot中不要应用 -->        <!-- 不是starter,手动配置 --><!--        <dependency>--><!--            <groupId>org.springframework.security.oauth</groupId>--><!--            <artifactId>spring-security-oauth2</artifactId>--><!--            <version>2.3.4.RELEASE</version>--><!--        </dependency>-->        <!--        </dependency>-->        <!-- 此oauth2依赖为spingcloud依赖,在springboot中不要应用 -->        <!--MQTT-->        <!-- 因为一些注解和API从spring security5.0中移除,所以须要导入上面的依赖包  -->        <!-- spring-boot-oauth2 -依赖于springboot2.0以上版本 -->        <dependency>            <groupId>org.springframework.security.oauth.boot</groupId>            <artifactId>spring-security-oauth2-autoconfigure</artifactId>            <version>2.0.0.RELEASE</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-integration</artifactId>            <!--            <version>2.4.0</version>-->        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-core -->        <dependency>            <groupId>org.springframework.integration</groupId>            <artifactId>spring-integration-core</artifactId>            <!--            <version>5.4.1</version>-->        </dependency>        <dependency>            <groupId>org.springframework.integration</groupId>            <artifactId>spring-integration-stream</artifactId>            <!--            <version>5.4.1</version>-->        </dependency>        <dependency>            <groupId>org.springframework.integration</groupId>            <artifactId>spring-integration-mqtt</artifactId>            <!--            <version>5.4.1</version>-->        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-mongodb</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-collections4</artifactId>            <version>4.1</version>        </dependency>    </dependencies></project>

OpenApiUtils

package com.baba.security.auth2.utils;import com.baba.security.auth2.constant.Oauth2Constant;import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.lang.Assert;import javax.servlet.http.HttpServletRequest;import java.util.Date;public class OpenApiUtils {    /**     * 获取用户id     *     * @param request     * @return     */    public static Long getUserId(HttpServletRequest request) {        String accessToken= request.getHeader("access_token");        Assert.hasText(accessToken, "accessToken parameter must not be empty or null");        final Claims claims = Jwts.parser()                .setSigningKey(Oauth2Constant.JWT_SIGNING_KEY.getBytes())                .parseClaimsJws(accessToken)                .getBody();        Long id = Long.valueOf(claims.get("id").toString());        return id;    }    /**     * 是否过期     *     * @param request     * @return     */    public static boolean isExpiration(HttpServletRequest request) {        String accessToken= request.getHeader("access_token");        Claims claims = Jwts.parser().setSigningKey(Oauth2Constant.JWT_SIGNING_KEY.getBytes()).parseClaimsJws(accessToken).getBody();        return claims.getExpiration().before(new Date());    }}

测试拜访的Controller:
HomeController

package com.baba.security.auth2.controller;import com.baba.security.auth2.utils.OpenApiUtils;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;/** * @Author wulongbo * @Date 2021/11/26 10:03 * @Version 1.0 */@RestController@RequestMapping("/home")public class HomeController {    @PreAuthorize("hasRole('/home/getHome')")    @RequestMapping("/getHome")    public String home(HttpServletRequest request) {        Long id = OpenApiUtils.getUserId(request);        return "home page" + id;    }    @PreAuthorize("hasRole('/home/getindex')")    @RequestMapping("/getindex")    public String index(HttpServletRequest request) {        Long id = OpenApiUtils.getUserId(request);        return "index page:" + id;    }}

ResController

package com.baba.security.auth2.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.security.Principal;/** * @Author wulongbo * @Date 2021/11/26 10:04 * @Version 1.0 */@RestControllerpublic class ResController {    @RequestMapping("/res/getMsg")    public String getMsg(String msg, Principal principal) {//principal中封装了客户端(用户,也就是clientDetails,区别于Security的UserDetails,其实clientDetails中也封装了UserDetails),不是必须的参数,除非你想得到用户信息,才加上principal。        return "Get the msg: "+msg;    }}

UserController

package com.baba.security.auth2.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.security.Principal;/** * 用户服务接口 * * @author Tom * @date 2020-09-04 */@RestControllerpublic class UserController {    @RequestMapping("/user")    public Principal user(Principal principal) {        //principal在通过security拦挡后,是org.springframework.security.authentication.UsernamePasswordAuthenticationToken        //在经OAuth2拦挡后,是OAuth2Authentication        return principal;    }}

oauth_client_details表调整sql:

SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for oauth_client_details-- ----------------------------DROP TABLE IF EXISTS `oauth_client_details`;CREATE TABLE `oauth_client_details`  (  `client_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主键,必须惟一,用于惟一标识每一个客户端',  `resource_ids` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '客户端所能拜访的资源id汇合',  `client_secret` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用于指定客户端的拜访密匙',  `scope` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '指定客户端申请的权限范畴,可选值包含read,write,trust',  `authorized_grant_types` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '指定客户端反对的grant_type,可选值包含 authorization_code,password,refresh_token,implicit,client_credentials',  `web_server_redirect_uri` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '客户端的重定向URI',  `authorities` varbinary(6000) NULL DEFAULT NULL COMMENT '指定客户端所领有的Spring Security的权限值',  `access_token_validity` int(11) NULL DEFAULT NULL COMMENT '设定客户端的access_token的无效工夫值',  `refresh_token_validity` int(11) NULL DEFAULT NULL COMMENT '设定客户端的refresh_token的无效工夫值(单位:秒),可选, 若不设定值则应用默认的无效工夫值(60 * 60 * 24 * 30, 30天).',  `additional_information` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '这是一个预留的字段,在Oauth的流程中没有理论的应用,可选,但若设置值,必须是JSON格局的 数据',  `autoapprove` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设置用户是否主动Approval操作, 默认值为 ‘false’',  PRIMARY KEY (`client_id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;-- ------------------------------ Records of oauth_client_details-- ----------------------------INSERT INTO `oauth_client_details` VALUES ('baidu', 'mayikt_resource,user,device', '$2a$10$32N/ptu3jY0WjFH0qLbcEO2ZcCg4gYCJvMbwmqzf84qNCcDFBLl4q', 'read,write', 'authorization_code', 'http://www.mayikt.com/callback', NULL, NULL, NULL, NULL, NULL);INSERT INTO `oauth_client_details` VALUES ('mayikt_appid', NULL, '$2a$10$6/Sab9Au.CdKqyE4x0gr0OJZrzrcDCWZ9GLqMDF6KX.jHad5vlkeO', 'read,write,trust', 'authorization_code,refresh_token,client_credentials', 'http://localhost:8082/res/getMsg', NULL, 36000, 36000, NULL, '1');INSERT INTO `oauth_client_details` VALUES ('zdfd', 'mayikt_resource', '$2a$10$6/Sab9Au.CdKqyE4x0gr0OJZrzrcDCWZ9GLqMDF6KX.jHad5vlkeO', 'read,write,trust', 'authorization_code', 'http://www.mayikt.com/callback', NULL, NULL, NULL, NULL, NULL);SET FOREIGN_KEY_CHECKS = 1;

浏览器中输出如下地址:获取受权码code:
http://localhost:8082/oauth/authorize?client_id=mayikt_appid&response_type=code&redirect_uri=http://localhost:8082/res/getMsg

咱们用户名为手机号,输出手机号17343759359,明码132465[后盾会MD5加密比对]

点击受权,获取受权码

依据受权码获取access_token:
**备注:**有的文章说这里申请头中需带 Authrization:加上工具类GetSecret生成的Basic bWF5aWt0X2FwcGlkOjEyMzQ1Ng==,然而我测试不加也行

localhost:8082/oauth/token
form-data参数如下

参数参数值
grant_typeauthorization_code
codeZXfgp3
client_idmayikt_appid
client_secret123456
redirect_urihttp://localhost:8082/res/getMsg

查看access_token:
http://localhost:8082/oauth/c...

咱们拜访一下资源服务:
http://localhost:8082/res/get...

拜访咱们权限管制的controller
http://localhost:8082/home/ge...

当然咱们的17343759359用户我给了所有权限,我登录一个没有getindex权限的用户13549553864时候,申请/home/getindex看一看【已免去后面的受权步骤】
http://localhost:8082/home/ge...
拜访失败

自此咱们实现了jwt形式来实现凋谢接口平台