本筆記用於記錄微信掃碼登陸過程當中遇到的問題
目的:React嵌入iframe微信掃碼登陸html
流程git
內容 | 版本 |
---|---|
Cas | 5.3.1 |
微信 | - |
springboot | 1.5.13 |
域名 | 做用 |
---|---|
https://cas.demo.com | Cas服務端 |
https://gateway.demo.com | SpringCloud網關 |
https://gateway.demo.com/app/... | Cas客戶端(由網關進行負載) |
添加依賴github
<dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-pac4j-webflow</artifactId> <version>${cas.version}</version> </dependency>
配置文件web
application.propertiesredis
#WeChat OAuth Login cas.authn.pac4j.oauth2[0].id=wxac0f1c863937d887 #因爲微信的不爲clinet_id,爲appid cas.authn.pac4j.oauth2[0].customParams.appid=wxac0f1c863937d887 #微信scope登陸爲snsapi_login cas.authn.pac4j.oauth2[0].customParams.scope=snsapi_login cas.authn.pac4j.oauth2[0].secret=cceedc350fe15f45315a0ab67643085e cas.authn.pac4j.oauth2[0].authUrl=https://open.weixin.qq.com/connect/qrconnect #todo 能夠添加中轉程序來作這個事情 cas.authn.pac4j.oauth2[0].tokenUrl=https://gateway.demo.com/app/auth/weixin/access_token cas.authn.pac4j.oauth2[0].profileUrl=https://gateway.demo.com/app/auth/weixin/userinfo cas.authn.pac4j.oauth2[0].clientName=WeChat
配置文件算法
cas.propertiesspring
cas.server.prefix=https://cas.demo.com
or數據庫
--cas.server.prefix=https://cas.demo.com/cas
api
注:此處不容許使用端口,否則會顯示參數錯誤緩存
分佈式部署配置
<dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp-session-redis</artifactId> <version>${cas.version}</version> </dependency>
application.properties
cas.ticket.registry.redis.host=${spring.redis.host} cas.ticket.registry.redis.database=10 cas.ticket.registry.redis.port=${spring.redis.port} cas.ticket.registry.redis.password=${spring.redis.password} cas.ticket.registry.redis.timeout=2000 cas.ticket.registry.redis.useSsl=false cas.ticket.registry.redis.usePool=true cas.ticket.registry.redis.pool.max-active=20 cas.ticket.registry.redis.pool.maxIdle=8 cas.ticket.registry.redis.pool.minIdle=0 cas.ticket.registry.redis.pool.maxActive=8 cas.ticket.registry.redis.pool.maxWait=-1 cas.ticket.registry.redis.pool.numTestsPerEvictionRun=0 cas.ticket.registry.redis.pool.softMinEvictableIdleTimeMillis=0 cas.ticket.registry.redis.pool.minEvictableIdleTimeMillis=0 cas.ticket.registry.redis.pool.lifo=true cas.ticket.registry.redis.pool.fairness=false # 設置ticket的加密算法,以保證分佈式部署適合ticket結果一致 cas.tgc.crypto.encryption.key=${encryption_key} cas.tgc.crypto.signing.key=${signing_key} # session緩存化 cas.webflow.autoconfigure=true cas.webflow.alwaysPauseRedirect=false cas.webflow.refresh=true cas.webflow.redirectSameState=false cas.webflow.session.lockTimeout=30 cas.webflow.session.compress=false cas.webflow.session.maxConversations=5 cas.webflow.session.storage=true srping.session.store-type=redis
POM.xml
<dependency> <groupId>net.unicon.cas</groupId> <artifactId>cas-client-autoconfig-support</artifactId> <version>1.4.0-GA</version> </dependency> <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.5.0</version> </dependency>
application.yml
cas: #cas服務端前綴,不是登陸地址 server-url-prefix: https://cas.demo.com #cas的登陸地址 server-login-url: https://cas.demo.com/login #當前客戶端地址 client-host-url: https://gateway.demo.com/app/auth #指定ticket校驗器 validation-type: CAS3 authenticationUrlPatterns: - /cas/login - /app/auth/cas/login validationUrlPatterns: - /cas/login - /app/auth/cas/login requestWrapperUrlPatterns: - /cas/login - /app/auth/cas/login auth: wechat: appid: wxac0f1c863937d887 secret: cceedc350fe15f45315a0ab67643085e access_token: https://api.weixin.qq.com/sns/oauth2/access_token userinfo: https://api.wexin.qq.com/sns/userinfo loginComplete: /loginComplete service: https://gateway.demo.com/app/auth/cas/login
CasConfig
@Configuration public class CasConfig extends CasClientConfiggurerAdapter { @Value("${auth.service}") private String AUTH_SERVICE; @Override public void configureValidationFilter(FilterRegistrationBean validationFilter){ super.configureValidationFilter(validationFilter); validationFilter.getInitParameters().put("redirectAfterValidation","false"); validationFilter.getInitParameters().remove("serverName"); validationFilter.getInitParameters().put("service",AUTH_SERVICE); } }
ProxyController
@RestController @RequestMapping("") public class ProxyController { @Autowired private StringRedisTemplate stringRedisTemplate @Value("${auth.loginComplete}") private String AUTH_LOGIN_COMPLETE; @Value("${auth.wechat.appid}") private String AUTH_WECHAT_APPID; @Value("${auth.wechat.secret}") private String AUTH_WECHAT_SECRET; @Value("${auth.wechat.access_token}") private String AUTH_WECHAT_ACCESS_TOKEN; @Value("${auth.wechat.userinfo}") private String AUTH_WECHAT_USERINFO; @PostMapping(value = "/weixin/access_token") public Object weixinAccessToken(@RequestBody String body){ Map<String, String> param=RequestUrlParamUtls.getParam(body); StringBuidder url= new StringBuilder(); url.append(AUTH_WECHAT_ACCESS_TOKEN+"?"); url.append("appid="+AUTH_WECHAT_APPID); url.append("&secret="+AUTH_WECHAT_SECRET); url.append("&code="+param.get("code")); url.append("&grant_type=authorization_code"); RestTemplate restTemplate = RequestUrlParamUtils.getInstance(); String weAppBody=restTemplate.postForObject(url.toString(),null,String.class); String weChatToken="auth_weChat_"+JSON.parseObject(weAppBody).getString("access_token"); stringRedisTemplate.opsForValue().set(weChatToken,weAppBody,1,TimeUnit.HOURS); return JSON.parseObject(weAppBody,Map.class); } @PostMapping(value = "/weixin/userinfo") public Object weixinUserinfo(@RequestBody String body){ String access_token=body.split("=")[1]; StringBuilder url=new StringBuilder(); String weChatToken="auth_weChat_"+access_token; String weAppBody=stringRedisTemplate.opsForValue().get(weChatToken); url.append(AUTH_WECHAT_USERINFO+"?"); url.append("access_token="); url.append(access_token); url.append("&openid="); url.append(JSON.parseObject(weAppBody).getSAtring("openid")); RestTemplate restTemplate = RequestUrlParamUtils.getInstance(); String infoBody=restTemplate.postForObject(url.toString(),null,String.class); return JSON.parseObject(infoBody,Map.class); } @GetMapping(value = "/cas/login") public Object casLogin(HttpServletRequest request,HttpServletResponse response){ AttributePrincipal ap=AssertionHolder.getAssertion().getPrincipal(); // TODO: 這裏能夠拿到用戶信息,持久化到數據庫。(此處待補充rest鏈接cas) StringBuilder url=new StringBuilder(); url.append(AUTH_LOGIN_COMPLETE); // TODO:此處將返回信息寫到參數裏 response.sendRedirect(url.toString()); return null; } }
1、嵌入訪問鏈接
https://cas.demo.com/clientredirect?client_name=WeChat&service=https://gateway.demo.com/app/auth/cas/login
2、定向到微信掃碼頁
https://open.weixin.qq.com/connet/grconect?xxxxxx
3、掃碼完成,重定向回到cas
https://cas.demo.com/login?client_name=WeChat&codexxx&state=xxx
4、cas校驗完成後重定向到客戶端服務器
https://gateway.demo.com/app/auth/cas/login?ticket=xxx
5、客戶端服務器重定向到靜態頁
https://gateway.demo.com/app/auth/login_complate?status=up&token=
會自動跳轉到微信掃碼受權界面,並填寫完成回調url
https://gitee.com/Kawhi-Carl/sso
http://www.ibloger.net/articl...
http://www.cassso-china.cn/ap...