新增二维码验证登录模式
This commit is contained in:
parent
74ae51d555
commit
c709f93449
12
pom.xml
12
pom.xml
@ -65,6 +65,8 @@
|
||||
<commons-collections4.version>4.4</commons-collections4.version>
|
||||
<commons-io.version>2.11.0</commons-io.version>
|
||||
<commons-crypto.version>1.1.0</commons-crypto.version>
|
||||
<hutool.version>5.8.8</hutool.version>
|
||||
<zxing.version>3.5.0</zxing.version>
|
||||
<!-- 文档-->
|
||||
<knife4j.version>3.0.3</knife4j.version>
|
||||
<!--编译编码-->
|
||||
@ -250,6 +252,16 @@
|
||||
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
|
||||
<version>${shardingsphere.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${zxing.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
@ -77,6 +77,15 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -1,20 +1,30 @@
|
||||
package cn.zyjblogs.config.security;
|
||||
|
||||
import cn.zyjblogs.config.security.policy.OauthAuthorizationCodeServices;
|
||||
import cn.zyjblogs.config.security.policy.QrCodeTokenGranter;
|
||||
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
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.ClientDetailsService;
|
||||
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
||||
import org.springframework.security.oauth2.provider.TokenRequest;
|
||||
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
|
||||
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
|
||||
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
||||
@ -22,6 +32,7 @@ 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;
|
||||
|
||||
/**
|
||||
@ -81,13 +92,13 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
|
||||
*/
|
||||
@Override
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
|
||||
|
||||
endpoints
|
||||
//密码模式
|
||||
.authenticationManager(authenticationManager)
|
||||
// .authenticationManager(authenticationManager)
|
||||
//授权码模式
|
||||
.authorizationCodeServices(authorizationCodeServices(dataSource))
|
||||
.tokenServices(tokenServices())
|
||||
// .authorizationCodeServices(authorizationCodeServices())
|
||||
// .tokenServices(tokenServices())
|
||||
.tokenGranter(tokenGranter(endpoints))
|
||||
.accessTokenConverter(accessTokenConverter)
|
||||
//允许表单认证
|
||||
.allowedTokenEndpointRequestMethods(HttpMethod.POST)
|
||||
@ -95,6 +106,39 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
|
||||
.exceptionTranslator(oAuthResponseExceptionTranslator);
|
||||
}
|
||||
|
||||
private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
return new TokenGranter() {
|
||||
private CompositeTokenGranter delegate;
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
|
||||
if (delegate == null) {
|
||||
delegate = getTokenGranters(endpoints);
|
||||
}
|
||||
return delegate.grant(grantType, tokenRequest);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* m
|
||||
* 授权模式
|
||||
*
|
||||
* @param endpoints
|
||||
* @return
|
||||
*/
|
||||
private CompositeTokenGranter getTokenGranters(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
List<TokenGranter> list = new ArrayList<>();
|
||||
list.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
list.add(new RefreshTokenGranter(tokenServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
list.add(new AuthorizationCodeTokenGranter(tokenServices(), authorizationCodeServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
list.add(new ImplicitTokenGranter(tokenServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
list.add(new ClientCredentialsTokenGranter(tokenServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
list.add(new QrCodeTokenGranter(tokenServices(), clientDetails(dataSource), endpoints.getOAuth2RequestFactory()));
|
||||
return new CompositeTokenGranter(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 令牌管理服务
|
||||
*
|
||||
@ -128,7 +172,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {
|
||||
public AuthorizationCodeServices authorizationCodeServices() {
|
||||
//设置授权码模式的授权码如何存取
|
||||
return new OauthAuthorizationCodeServices(redisTemplateHandler);
|
||||
// return new JdbcAuthorizationCodeServices(dataSource);
|
||||
|
@ -13,6 +13,8 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.R
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zhuyijun
|
||||
*/
|
||||
@ -48,18 +50,19 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
|
||||
*/
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
List<String> allowPaths = whiteListProperties.getAllowPaths();
|
||||
String[] strings = allowPaths.toArray(new String[0]);
|
||||
http.csrf().disable()
|
||||
// .disable()
|
||||
//限制资源服务器作用范围为 "/user/**", "/demo/**"
|
||||
.requestMatchers().antMatchers("/v*/**", "/demo/**",
|
||||
String.join(",", whiteListProperties.getAllowPaths()))
|
||||
.requestMatchers().antMatchers("/v*/**", "/demo/**").antMatchers(strings)
|
||||
.and()
|
||||
.formLogin()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(String.join(",", whiteListProperties.getAllowPaths()))
|
||||
.antMatchers(strings).permitAll()
|
||||
.antMatchers("/v*/user/login", "/v*/auth/refresh/token", "/v*/auth/authorize/code")
|
||||
.permitAll()
|
||||
.antMatchers("/v*/user/login", "/v*/auth/refresh/token", "/v*/auth/authorize/code").permitAll()
|
||||
.antMatchers("/v*/**").access("#oauth2.hasAnyScope('oauth','all')")
|
||||
//以下请求必须认证通过
|
||||
.anyRequest()
|
||||
|
@ -53,7 +53,11 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable();
|
||||
//使HttpSecurity接收以"/login/","/oauth/"开头请求, 配置HttpSecurity不阻止swagger页面
|
||||
http.authorizeRequests()
|
||||
http
|
||||
// .requestMatchers().antMatchers("/login")
|
||||
// .and()
|
||||
.authorizeRequests()
|
||||
|
||||
// .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**")
|
||||
// .permitAll()
|
||||
// .antMatchers("/user/logout", "/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll()
|
||||
|
@ -0,0 +1,26 @@
|
||||
package cn.zyjblogs.config.security.policy;
|
||||
|
||||
import cn.zyjblogs.server.user.dto.AuthorizationDto;
|
||||
import org.springframework.security.oauth2.provider.*;
|
||||
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
|
||||
public class QrCodeTokenGranter extends AbstractTokenGranter {
|
||||
private static final String GRANT_TYPE = "qrcode";
|
||||
|
||||
protected QrCodeTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
|
||||
super(tokenServices, clientDetailsService, requestFactory, grantType);
|
||||
}
|
||||
|
||||
public QrCodeTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService
|
||||
, OAuth2RequestFactory requestFactory) {
|
||||
this(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
|
||||
AuthorizationDto authorization = new AuthorizationDto().createAuthorization();
|
||||
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
|
||||
return new OAuth2Authentication(storedOAuth2Request, authorization);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.zyjblogs.server.qrcode.constant;
|
||||
|
||||
public enum QrCodeEnum {
|
||||
EXPIRE(0, "过期"),
|
||||
NO_EXPIRE(1, "过期"),
|
||||
NO_EXPIRE_HAS_TOKEN(2, "过期");
|
||||
|
||||
QrCodeEnum(int code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private int code;
|
||||
private String name;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package cn.zyjblogs.server.qrcode.controller;
|
||||
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import cn.zyjblogs.server.qrcode.dto.QrCode;
|
||||
import cn.zyjblogs.server.qrcode.service.QrCodeSerive;
|
||||
import cn.zyjblogs.server.user.handler.OauthRquestHander;
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
import cn.zyjblogs.starter.common.entity.response.HttpCode;
|
||||
import cn.zyjblogs.starter.common.entity.response.ResponseObject;
|
||||
import cn.zyjblogs.starter.common.entity.response.ResponseResult;
|
||||
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
|
||||
import cn.zyjblogs.starter.web.apiversion.ApiVersion;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiVersion(1)
|
||||
@RequestMapping("/{v}/qrcode")
|
||||
@RestController
|
||||
@ResponseBody
|
||||
@RequiredArgsConstructor
|
||||
public class QrCodeController {
|
||||
private final QrCodeSerive qrCodeSerive;
|
||||
@Value("${zyjblogs.qrcode.redirect_url}")
|
||||
private String qrcodeRedirectUrl;
|
||||
|
||||
//获取登录二维码、放入Token
|
||||
@GetMapping("/get")
|
||||
@ApiVersion(1)
|
||||
public void createCodeImg(HttpServletRequest request, HttpServletResponse response, @RequestParam("appid") String appid) {
|
||||
response.setHeader("Pragma", "No-cache");
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setContentType("image/jpeg");
|
||||
|
||||
try {
|
||||
QrCode qrCode = qrCodeSerive.createQrId(appid);
|
||||
Cookie cookie = new Cookie("qrsig", qrCode.getQrsig());
|
||||
response.addCookie(cookie);
|
||||
Map<String, String> query = new LinkedHashMap<>();
|
||||
query.put("k", qrCode.getQrsig());
|
||||
query.put("f", qrCode.getClienId());
|
||||
//这里没啥操作 就是生成一个UUID插入 数据库的表里
|
||||
QrCodeUtil.generate(OauthRquestHander.append(qrcodeRedirectUrl, query, false), 111, 111, "png", response.getOutputStream());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否过期
|
||||
*
|
||||
* @param k
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/isQrExpire")
|
||||
@ApiVersion(1)
|
||||
public Integer isQrExpire(@RequestParam("k") String k, @RequestParam("f") String f) {
|
||||
try {
|
||||
return qrCodeSerive.isQrExpire(k, f);
|
||||
} catch (Exception e) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录token
|
||||
*
|
||||
* @param k
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/login")
|
||||
@ApiVersion(1)
|
||||
public ResponseObject<OAuth2AccessTokenVo> getToken(@RequestParam("k") String k, @RequestParam("f") String f) {
|
||||
try {
|
||||
return ResponseResult.success(qrCodeSerive.getToken(k, f));
|
||||
} catch (Exception e) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cn.zyjblogs.server.qrcode.dto;
|
||||
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class QrCode implements Serializable {
|
||||
private String qrsig;
|
||||
private String clienId;
|
||||
private OAuth2AccessTokenVo token;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.zyjblogs.server.qrcode.service;
|
||||
|
||||
import cn.zyjblogs.server.qrcode.dto.QrCode;
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
|
||||
public interface QrCodeSerive {
|
||||
/**
|
||||
* 获取验证码id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
QrCode createQrId(String clientId);
|
||||
|
||||
/**
|
||||
* 校验验证码是否过期
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Integer isQrExpire(String qrsig, String clientId);
|
||||
|
||||
OAuth2AccessTokenVo getToken(String qrsig, String clientId);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package cn.zyjblogs.server.qrcode.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.zyjblogs.server.qrcode.constant.QrCodeEnum;
|
||||
import cn.zyjblogs.server.qrcode.dto.QrCode;
|
||||
import cn.zyjblogs.server.qrcode.service.QrCodeSerive;
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
|
||||
import cn.zyjblogs.starter.common.entity.response.HttpCode;
|
||||
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
|
||||
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class QrCodeSeriveImpl implements QrCodeSerive {
|
||||
private final RedisTemplateHandler<String, QrCode> redisTemplateHandler;
|
||||
|
||||
@Override
|
||||
public QrCode createQrId(String clientId) {
|
||||
if (clientId == null) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "appid不能为空");
|
||||
}
|
||||
String id2 = IdUtil.objectId();
|
||||
QrCode qrCode = QrCode.builder()
|
||||
.clienId(clientId)
|
||||
.qrsig(id2)
|
||||
.build();
|
||||
redisTemplateHandler.set(getRediKey(qrCode.getQrsig(), qrCode.getClienId()), null, 3, TimeUnit.MINUTES);
|
||||
return qrCode;
|
||||
}
|
||||
|
||||
public String getRediKey(String qrsig, String clientId) {
|
||||
return CommonRedisKeyConstant.QR_CODE + ":" + clientId + ":" + qrsig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer isQrExpire(String qrsig, String clientId) {
|
||||
String rediKey = getRediKey(qrsig, clientId);
|
||||
Boolean aBoolean = redisTemplateHandler.hasKey(rediKey);
|
||||
if (!aBoolean) {
|
||||
return QrCodeEnum.EXPIRE.getCode();
|
||||
}
|
||||
QrCode qrCode = redisTemplateHandler.get(rediKey);
|
||||
if (qrCode == null) {
|
||||
return QrCodeEnum.EXPIRE.getCode();
|
||||
}
|
||||
if (qrCode.getToken() == null) {
|
||||
return QrCodeEnum.NO_EXPIRE.getCode();
|
||||
}
|
||||
return QrCodeEnum.NO_EXPIRE_HAS_TOKEN.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenVo getToken(String qrsig, String clientId) {
|
||||
QrCode qrCode = redisTemplateHandler.get(getRediKey(qrsig, clientId));
|
||||
if (qrCode != null && qrCode.getToken() != null) {
|
||||
return qrCode.getToken();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -5,17 +5,16 @@ import cn.zyjblogs.server.user.dto.AuthorizationCodeDto;
|
||||
import cn.zyjblogs.server.user.dto.OAuth2AccessTokenDto;
|
||||
import cn.zyjblogs.server.user.service.AuthService;
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
import cn.zyjblogs.starter.common.entity.response.HttpCode;
|
||||
import cn.zyjblogs.starter.common.entity.response.ResponseObject;
|
||||
import cn.zyjblogs.starter.common.entity.response.ResponseResult;
|
||||
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
|
||||
import cn.zyjblogs.starter.web.apiversion.ApiVersion;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author zhuyijun
|
||||
@ -55,4 +54,14 @@ public class AuthController {
|
||||
public ResponseObject<OAuth2AccessTokenVo> getTokenByAuthorizationCode(@RequestBody @Validated AuthCodeDto authCodeDto) {
|
||||
return ResponseResult.success(authService.getTokenByAuthorizationCode(authCodeDto));
|
||||
}
|
||||
|
||||
@GetMapping("/qrcode/scan")
|
||||
@ApiVersion(1)
|
||||
public ResponseObject<Boolean> qrcodeScan(@RequestParam("k") String k, @RequestParam("f") String f) {
|
||||
try {
|
||||
return ResponseResult.success(authService.qrcodeScan(k, f));
|
||||
} catch (Exception e) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.zyjblogs.server.user.dto;
|
||||
|
||||
import cn.zyjblogs.server.user.po.OauthUserDetails;
|
||||
import cn.zyjblogs.starter.common.entity.context.BaseContext;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
@ -98,4 +100,16 @@ public class AuthorizationDto implements Authentication {
|
||||
public void setAuthenticated(Boolean authenticated) {
|
||||
this.authenticated = authenticated;
|
||||
}
|
||||
|
||||
public AuthorizationDto createAuthorization() {
|
||||
AuthorizationDto authorizationDto = new AuthorizationDto();
|
||||
OauthUserDetails oauthUserDetails = new OauthUserDetails();
|
||||
oauthUserDetails.setId(BaseContext.getUserId());
|
||||
oauthUserDetails.setName(BaseContext.getName());
|
||||
oauthUserDetails.setUsername(BaseContext.getUsername());
|
||||
oauthUserDetails.setTenantId(BaseContext.getTenantId());
|
||||
authorizationDto.setPrincipal(oauthUserDetails);
|
||||
authorizationDto.setAuthenticated(true);
|
||||
return authorizationDto;
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,7 @@ import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author zhuyijun
|
||||
@ -141,7 +135,7 @@ public class OauthRquestHander {
|
||||
return builder.build().toUriString();
|
||||
}
|
||||
|
||||
private static String append(String base, Map<String, ?> query, boolean fragment) {
|
||||
public static String append(String base, Map<String, ?> query, boolean fragment) {
|
||||
return append(base, query, (Map) null, fragment);
|
||||
}
|
||||
|
||||
|
@ -39,4 +39,13 @@ public interface AuthService {
|
||||
* @date 2022/10/15
|
||||
*/
|
||||
OAuth2AccessTokenVo getTokenByAuthorizationCode(AuthCodeDto authCodeDto);
|
||||
|
||||
/**
|
||||
* 二维码扫码登录
|
||||
*
|
||||
* @param k
|
||||
* @param f
|
||||
* @return
|
||||
*/
|
||||
Boolean qrcodeScan(String k, String f);
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package cn.zyjblogs.server.user.service.impl;
|
||||
|
||||
import cn.zyjblogs.server.qrcode.dto.QrCode;
|
||||
import cn.zyjblogs.server.user.dto.AuthCodeDto;
|
||||
import cn.zyjblogs.server.user.dto.AuthorizationCodeDto;
|
||||
import cn.zyjblogs.server.user.dto.AuthorizationDto;
|
||||
import cn.zyjblogs.server.user.dto.OAuth2AccessTokenDto;
|
||||
import cn.zyjblogs.server.user.handler.OauthRequestValidator;
|
||||
import cn.zyjblogs.server.user.handler.OauthRquestHander;
|
||||
import cn.zyjblogs.server.user.po.OauthUserDetails;
|
||||
import cn.zyjblogs.server.user.service.AuthService;
|
||||
import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo;
|
||||
import cn.zyjblogs.starter.common.entity.context.BaseContext;
|
||||
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
|
||||
import cn.zyjblogs.starter.common.entity.response.HttpCode;
|
||||
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
|
||||
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@ -33,6 +34,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author zhuyijun
|
||||
@ -46,11 +48,14 @@ public class AuthServiceImpl implements AuthService {
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private RedirectResolver redirectResolver;
|
||||
private OauthRequestValidator oauthRequestValidator;
|
||||
private RedisTemplateHandler redisTemplateHandler;
|
||||
private final Object implicitLock = new Object();
|
||||
|
||||
public AuthServiceImpl(AuthorizationServerEndpointsConfiguration authorizationServerEndpointsConfiguration,
|
||||
ClientDetailsService clientDetails,
|
||||
AuthorizationCodeServices authorizationCodeServices, PasswordEncoder passwordEncoder, OauthRequestValidator oauthRequestValidator) {
|
||||
AuthorizationCodeServices authorizationCodeServices, PasswordEncoder passwordEncoder,
|
||||
OauthRequestValidator oauthRequestValidator,
|
||||
RedisTemplateHandler redisTemplateHandler) {
|
||||
this.tokenGranter = authorizationServerEndpointsConfiguration.getEndpointsConfigurer().getTokenGranter();
|
||||
this.clientDetails = clientDetails;
|
||||
this.redirectResolver = new DefaultRedirectResolver();
|
||||
@ -58,6 +63,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
this.authorizationCodeServices = authorizationCodeServices;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.oauthRequestValidator = oauthRequestValidator;
|
||||
this.redisTemplateHandler = redisTemplateHandler;
|
||||
}
|
||||
|
||||
@Value("${security.oauth2.client.client-id}")
|
||||
@ -139,14 +145,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
if (responseTypes.contains("token")) {
|
||||
return getImplicitGrantResponse(authorizationRequest);
|
||||
}
|
||||
AuthorizationDto authorizationDto = new AuthorizationDto();
|
||||
OauthUserDetails oauthUserDetails = new OauthUserDetails();
|
||||
oauthUserDetails.setId(BaseContext.getUserId());
|
||||
oauthUserDetails.setName(BaseContext.getName());
|
||||
oauthUserDetails.setUsername(BaseContext.getUsername());
|
||||
oauthUserDetails.setTenantId(BaseContext.getTenantId());
|
||||
authorizationDto.setPrincipal(oauthUserDetails);
|
||||
authorizationDto.setAuthenticated(true);
|
||||
AuthorizationDto authorizationDto = new AuthorizationDto().createAuthorization();
|
||||
try {
|
||||
return OauthRquestHander.getSuccessfulRedirect(authorizationRequest,
|
||||
generateCode(authorizationRequest, authorizationDto));
|
||||
@ -179,6 +178,32 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean qrcodeScan(String k, String f) {
|
||||
Boolean aBoolean = redisTemplateHandler.hasKey(CommonRedisKeyConstant.QR_CODE + ":" + f + ":" + k);
|
||||
if (!aBoolean) {
|
||||
return false;
|
||||
}
|
||||
ClientDetails clientDetail = clientDetails.loadClientByClientId(f);
|
||||
if (clientDetail == null) {
|
||||
throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "该appid不存在");
|
||||
}
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put("grant_type", "qrcode");
|
||||
parameters.put("k", k);
|
||||
parameters.put("f", f);
|
||||
TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, clientDetail);
|
||||
OAuth2AccessToken token = tokenGranter.grant(tokenRequest.getGrantType(), tokenRequest);
|
||||
OAuth2AccessTokenVo oAuth2AccessTokenVo = OAuth2AccessTokenVo.TransferToken(token);
|
||||
QrCode qrCode = QrCode.builder()
|
||||
.qrsig(k)
|
||||
.clienId(f)
|
||||
.token(oAuth2AccessTokenVo)
|
||||
.build();
|
||||
redisTemplateHandler.set(CommonRedisKeyConstant.QR_CODE + ":" + f + ":" + k, qrCode, 5, TimeUnit.MINUTES);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理
|
||||
*
|
||||
|
@ -4,7 +4,10 @@ import cn.zyjblogs.starter.common.entity.constant.ContextKeyConstant;
|
||||
import cn.zyjblogs.starter.common.entity.context.BaseContext;
|
||||
import cn.zyjblogs.starter.common.entity.dto.ContextDto;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -17,6 +20,9 @@ import java.util.Set;
|
||||
* @author zhuyijun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class OAuth2AccessTokenVo implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty(value = "access token", dataType = "String", example = "abc.efg.hjk")
|
||||
|
@ -18,6 +18,8 @@ public class CommonRedisKeyConstant {
|
||||
*/
|
||||
public static final String XSRF_TOKEN = "XSRF_TOKEN:";
|
||||
|
||||
public static final String QR_CODE = "OAUTH:QR_CODE:";
|
||||
|
||||
private CommonRedisKeyConstant() {
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.R
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源服务
|
||||
*
|
||||
@ -44,10 +46,13 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
List<String> allowPaths = whiteListProperties.getAllowPaths();
|
||||
String[] strings = allowPaths.toArray(new String[0]);
|
||||
String scopeRs = "#oauth2.hasAnyScope(" + '\'' + scope + '\'' + ",'all')";
|
||||
http.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", String.join(",", whiteListProperties.getAllowPaths())).permitAll()
|
||||
.antMatchers(strings).permitAll()
|
||||
.antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**").permitAll()
|
||||
.antMatchers("/**").access(scopeRs)
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
|
Loading…
Reference in New Issue
Block a user