当前位置:   article > 正文

SpringCloud security +oauht2.0 授权码(authorization_code)模式+jwt 实现微服务的认证和授权(一)_java springcloud oauth2.0 授权码模式

java springcloud oauth2.0 授权码模式

1.授权码模式讲解

在这里插入图片描述
1.1:根据图片 我们看的出来 用户认证以后 我们拿到授权码 根据授权码 去获取token,那这个认证的过程 我们就不用去做了,我们只管用户登录成功以后 我们来拿到token

1.2:把password模式修改成 authorization_code 模式
password模式 如果你是看我这个文章来的 我们只需要 修改以下内容,如果你是新来了,可以去我的gitHub看这篇文章的源码 源码地址
1.3:修改 WebSecurityConfig 文件

package com.example.springcloudalibabaoauthauth.security;

import com.example.springcloudalibabaoauthauth.service.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * 2 * @Author: ZhangShuai
 * 3 * @Date: 2020/6/12 17:03
 * 4
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //使用Security的认证管理器  认证操作security 给我们来做
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


    //使用security的默认密码加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean  //主要是配置这个Bean,用于授权服务器配置中注入
    @Override
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl();
    }

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

    //配置security不拦截的请求  下面可以根据需求自定义 用,号隔开
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 将 check_token 暴露出去,否则资源服务器访问时报 403 错误
        //配置暴露出去的端点  不用登陆就可以访问
        web.ignoring().antMatchers( "/GetToken", "/index.html", "/css/**", "/js/**",
                "/images/**",
                "/openid/login",
                "/oauth/check_token", "/queryToken");
    }

    //增加了这个方法
    @Override
    public void configure(HttpSecurity http) throws Exception {
        //禁止跨域请求
        http.csrf().disable()
                .formLogin()
                .loginPage("/index.html")  //不使用 security的登录页面 使用我们自己的登录页面
                .loginProcessingUrl("/loginSubmit")  //登录表单要提交的地址 这个地址不需要存在  保证表单提交的地址 和我们这里写的地址 是一样的
                .defaultSuccessUrl("/loginSuccess")  //登录 成功 要跳转的地址 这里 还有一个参数 是boolean类型的 默认为false
                .and()
                .authorizeRequests().anyRequest().authenticated();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

1.4:修改 JwtUser 实体类的内容

package com.example.springcloudalibabaoauthauth.util;

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

import java.util.Collection;
/**
 * Created by zhangshuai on 2020/6/22.
 */
@Data
public class JwtUser extends User {

    /**
     * 用户id
     */
    private Long id;

    /**
     * 用户名
     */
    private String username;

    /**
     *账号
     */
    private  boolean accountNonExpired;
    /**
     *账号是否被锁定
     */
    private  boolean accountNonLocked;
    /**
     * 帐号是否过期
     */
    private  boolean credentialsNonExpired;
    /**
     * 帐号是否被禁用
     */
    private  boolean enabled;

    /**
     * 构造方法
     * @param username
     * @param password
     * @param authorities
     * @param accountNonExpired
     * @param accountNonLocked
     * @param credentialsNonExpired
     * @param enabled
     */
    public JwtUser(String username, String password, Collection<? extends GrantedAuthority> authorities,  boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled) {
        super(username, password, authorities);
        this.accountNonExpired = accountNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.credentialsNonExpired = credentialsNonExpired;
        this.enabled = enabled;
    }


    /**
     * 让boolean的都变为true
     * @param username 用户名
     * @param password 密码
     * @param authorities  权限
     */
    public JwtUser(String username, String password,
                Collection<? extends GrantedAuthority> authorities) {
        this(username, password, authorities, true, true, true,true );
    }

}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

1.5:修改 application.yml

server:
  port: 9090
spring:
  application:
    name: springcloud-oauth-auth
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.3.37/test?useUnicode=true&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
    password: zhangxiaoyun123
    username: root
  resources:
    static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/templates/
  thymeleaf:
    encoding: UTF-8
    suffix: .html
    cache: false
    # 配置前缀时必须加templates,浏览器访问页面时不加templates路径
    prefix: classpath:/templates/
#cloud:
#  nacos:
#    discovery:
#      #指定nacos server的地址
#      server-addr: 127.0.0.1:8848

logging:
  level:
    cloud.zxy.system: debug

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

2.增加 controller层

2.1 :AuthToken 定义返回令牌信息

package com.example.springcloudalibabaoauthauth.util;

import lombok.Data;

/**
 * Created by zhangshuai on 2020/6/22.
 */
@Data
public class AuthToken {
    /**
     * access_token
     */
    private String access_token;

    /**
     * 刷新令牌token
     */
    private String refresh_token;
    /**
     * jwt令牌
     */
    private String jwt_token;//jwt令牌

    /**
     * 令牌到期时间
     */
    private Integer expires_in;

    /**
     * 错误
     */
    private String error;

    /**
     * 申请令牌的错误信息
     */
    private String error_description;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

2.2 LoginController:使用code获取令牌的一些逻辑

package com.example.springcloudalibabaoauthauth.controller;

import com.example.springcloudalibabaoauthauth.util.AuthToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * 2 * @Author: ZhangShuai
 * 3 * @Date: 2020/6/20 11:22
 * 4
 */
@RestController
@Slf4j
public class LoginController {

    @Autowired
    private RestTemplate restTemplate;

    /*登录的方法*/
    @GetMapping("loginSuccess")
    public String login(){
        return "ok";
    }

    /**
     * 前端 可以根据这个地址 拿到token
     * 获取code 的回调地址
     * @param code
     * @return
     */
    @GetMapping("GetToken")
    public AuthToken GetToken(@RequestParam String code){

        //这里可以让前端 给你传一个 值 拿到这个值 可以进行回调到 这个url
        log.info("code is " + code);
        String authUrl = "http://localhost:9090/oauth/token";
        //定义header
        LinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        String httpBasic = getHttpBasic();
        header.add("Authorization", httpBasic);
        //定义body
        LinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "authorization_code");
        body.add("code", code);
        body.add("redirect_uri", "http://localhost:9090/GetToken");
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, header);
        //调用登录认证服务 生成jwt令牌
        ResponseEntity<Map> exchange = restTemplate.exchange(authUrl, HttpMethod.POST, httpEntity, Map.class);
        //申请令牌信息
        AuthToken authToken = makeAuthToken(exchange);
        return authToken;
    }

    /**
     * 设置token值
     *
     * @param exchange 远程调用结果
     * @return
     */
    private AuthToken makeAuthToken(ResponseEntity<Map> exchange) {
        Map bodyMap = exchange.getBody();
        AuthToken authToken = new AuthToken();
        if (bodyMap == null ||
                bodyMap.get("access_token") == null ||
                bodyMap.get("refresh_token") == null ||
                bodyMap.get("jti") == null ||
                bodyMap.get("expires_in") == null
        ) {
            authToken.setError((String) bodyMap.get("error"));
            authToken.setError_description((String) bodyMap.get("error_description"));
            return authToken;
        }
        authToken.setAccess_token((String) bodyMap.get("access_token"));//用户身份令牌
        authToken.setRefresh_token((String) bodyMap.get("refresh_token"));//刷新令牌
        authToken.setJwt_token((String) bodyMap.get("jti"));//jwt令牌
        return authToken;
    }

    /*获取httpBasic的串*/
    private String getHttpBasic() {
        String string = "client" + ":" + "admin";
        //将串进行base64编码
        byte[] encode = Base64Utils.encode(string.getBytes());
        return "Basic " + new String(encode);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100

2.3 resources:下面增加 static 和templates
在这里插入图片描述
下载链接:https://pan.baidu.com/s/1aG4APvMFluyDXu-YxD23zg
提取码:vdxj

3.测试授权码获取token

3.1:首先通过浏览器访问下面的地址获取授权码(code)

http://localhost:9090/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://localhost:9090/GetToken

注(这里的cilent 还有response_type 和 redirect_uri)必须在数据库配置 oauth_client_details
当我们访问上面地址的时候 会跳转到 首页让我们登录
在这里插入图片描述
3.2 登录成功 返回token
在这里插入图片描述
注意事项:
redirect_uri :必须保证和数据库的一致 不然会报这个错误
在这里插入图片描述
cilent :必须和数据库的一致
response_type=code:必须保证你配置了 授权码登录
源码地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/84431
推荐阅读
相关标签
  

闽ICP备14008679号