最近项目中要求使用oauth2.0 作为联合登录的认证服务端,由于之前没接触过这块于是摸索着学习并使用springboot+security+oauth2.0搭建认证服务端,从网上找了个demo在实际改造中还是遇到了一些坑,在此记录一下以便以后查看。
其中参考demo下载地址:
https://github.com/topsale/spring-boot-samples/tree/master/spring-security-oauth2
学习中参考文章地址:
https://www.funtl.com/zh/spring-security-oauth2/创建资源服务器模块.html
https://www.zifangsky.cn/1313.html
https://www.bilibili.com/video/av48590637?p=1&share_medium=android&share_source=qq&bbid=4BE35FA9-628E-4CD0-B93D-5F2BD8391FC715581infoc&ts=1561787800050
在此也感谢各位博主的分享
如下是本人在开发中遇到的一些问题在此一一列出(注意是在使用本问参考demo进行认证服务端整改时的问题):
1、在进入系统时必须通过该链接http://localhost:8080/oauth/authorize?client_id=client&response_type=code其会自动调转到登录页面
2、关于重写登录页面
首先在yml配置文件中添加thymeleaf配置如下图:
具体代码(注意对齐格式):
thymeleaf:
prefix: classpath:/views/
suffix: .html
cache: false
mvc:
throw-exception-if-no-handler-found: true
其次在WebSecurityConfiguration类中配置跳转路径:
代码如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 必须配置,不然OAuth2的http配置不生效----不明觉厉
.requestMatchers()
.antMatchers("/auth/login", "/auth/authorize","/oauth/authorize")
.and()
.authorizeRequests()
// 自定义页面或处理url是,如果不配置全局允许,浏览器会提示服务器将页面转发多次
.antMatchers("/auth/login", "/auth/authorize")
.permitAll()
.anyRequest()
.authenticated();
// 表单登录
http.formLogin()
// 登录页面
.loginPage("/auth/login")
// 登录处理url
.loginProcessingUrl("/auth/authorize");
http.httpBasic().disable();
}
最后在BaseMainController类中定义要跳转的登录页,即自己写的登录页
代码:
@GetMapping("/auth/login")
public String loginPage(Model model){
model.addAttribute("loginProcessUrl","/auth/authorize");
return "login";
}
3、关于重写授权页面
首先在AuthorizationServerConfiguration类中配置自定义调转接口
代码:
// 最后一个参数为替换之后授权页面的url
endpoints.pathMapping("/oauth/confirm_access","/custom/confirm_access");
然后在BootGrantController类中加载跳转到自定义页面
代码:
package com.funtl.oauth2.server.controller;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
@Controller
@SessionAttributes("authorizationRequest")
public class BootGrantController {
@RequestMapping("/custom/confirm_access")
public ModelAndView getAccessConfirmation(Map model, HttpServletRequest request) throws Exception {
AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest");
ModelAndView view = new ModelAndView();
view.setViewName("base-grant");
view.addObject("clientId", authorizationRequest.getClientId());
view.addObject("scopes",authorizationRequest.getScope());
return view;
}
}
4、自定义token及Refresh_token有效期
代码:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 设置令牌
endpoints.tokenStore(tokenStore()).userDetailsService(userDetailsService1());
// 最后一个参数为替换之后授权页面的url
endpoints.pathMapping("/oauth/confirm_access","/custom/confirm_access");
//endpoints.tokenServices(defaultTokenServices());
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(endpoints.getTokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
//tokenServices.setAccessTokenValiditySeconds(60);
tokenServices.setAccessTokenValiditySeconds(60*60*2);//token有效期设置2个小时
tokenServices.setRefreshTokenValiditySeconds(60*60*12);//Refresh_token:12个小时
endpoints.tokenServices(tokenServices);
}
5、设置授权登录时自动调过授权页面
在项目中要求自动跳过授权页面搜了很多资料说使用的有关配置一直都没效果,最后通过在数据库oauth_client_details表中通过配置autoapprove为true来实现自动跳过授权页,应该还有别的方式目前本人还没找到。
6、支持https请求
当时用http请求时一切正常,但是项目中要求使用https请求于是一顿操作最后还是在同事的协助下解决的此问题,在yml配置文件中通过配置tomcat可完美解决该问题:
代码(注意对齐关系):
server:
port: 8085
tomcat:
remote_ip_header: X-Forwarded-For
protocol_header: X-Forwarded-Proto
proxies_header: X-Forwarded-By
internal_proxies: 10\.\d{1,3}\.\d{1,3}\.\d{1,3}|100\.\d{1,3}\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.4[0-1]{1}\.\d{1,3}\.\d{1,3}|0:0:0:0:0:0:0:1|::1
@Override
public void configure(WebSecurity web) throws Exception {
// 将 check_token 暴露出去,否则资源服务器访问时报 403 错误
web.ignoring().antMatchers("/oauth/check_token");
web.ignoring().antMatchers("/auth/qylogin");//模拟登陆请求
}
8、关于重定向url
若第一次请求中携带redirect_uri则获取token时也必须携带同样的token,若第一次的重定向url编码了,获取token时携带的url不需用编码,因为第一次的编码到后台会自动解码,第二次的不会,且这两次请求都会对oauth_client_details表配置的web_server_redirect_uri进行校验,与传递的重定向url一样时校验才能通过。若第一请求中没有携带redirect_uri则第二次也不用,会直接使用库中配置的web_server_redirect_uri作为重定向url。而且传递参数时只能用redirect_uri作为重定向url参数名,如使用其它参数名则只会视为一个普通参数。
以上是初学遇到的问题,可能有些不对或不完善的地方望大家批评指正,QQ:2906010411