赞
踩
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.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.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
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; }
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); } }
2.3 resources:下面增加 static 和templates
下载链接:https://pan.baidu.com/s/1aG4APvMFluyDXu-YxD23zg
提取码:vdxj
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:必须保证你配置了 授权码登录
源码地址
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。