Commit 68dd0cdd authored by 董天德's avatar 董天德

Merge remote-tracking branch 'origin/dev_20230205_mq'

parents a392511e 0ff5381a
package com.hungraim.ltc.controller; package com.hungraim.ltc.controller;
import com.hungraim.ltc.util.CsoftSecurityUtil;
import com.hungraim.ltc.util.Result; import com.hungraim.ltc.util.Result;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal; import java.security.Principal;
import java.util.Map; import java.util.Map;
...@@ -19,17 +25,38 @@ import java.util.Map; ...@@ -19,17 +25,38 @@ import java.util.Map;
@RequestMapping("/oauth") @RequestMapping("/oauth")
@AllArgsConstructor @AllArgsConstructor
public class AuthController { public class AuthController {
private final TokenEndpoint tokenEndpoint; private final TokenEndpoint tokenEndpoint;
@PostMapping("/token") @PostMapping("/token")
@SneakyThrows @SneakyThrows
public Result<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) { public Result<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) {
String password = parameters.get("password");
String decrypt = CsoftSecurityUtil.decryptRSADefault(password);
parameters.put("password", decrypt);
OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody(); OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
return Result.success(oAuth2AccessToken); return Result.success(oAuth2AccessToken);
} }
/**
* 获取公钥
* @return
*/
@GetMapping("/genKeyPair")
public Result<String> genKeyPair() {
Map keyMap = CsoftSecurityUtil.createKeyPairs();
return Result.success(keyMap.get(0).toString());
}
@GetMapping("/authLogout")
public Result authLogout(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//清除认证
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return Result.success();
}
} }
package com.hungraim.ltc.controller; package com.hungraim.ltc.controller;
import com.hungraim.ltc.util.CsoftSecurityUtil;
import com.hungraim.ltc.util.Result;
import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.RSAKey;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.util.Map; import java.util.Map;
......
...@@ -58,7 +58,11 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu ...@@ -58,7 +58,11 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
this.userDetailsService = userDetailsService; this.userDetailsService = userDetailsService;
} }
/**
* 配置客户信息(jdbc方式获取用户信息)
* @param clients
* @throws Exception
*/
@Override @Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception { public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetails()); clients.withClientDetails(clientDetails());
...@@ -78,6 +82,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu ...@@ -78,6 +82,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
*/ */
@Override @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) { public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
//令牌增强器
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> tokenEnhancers = new ArrayList<>(); List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
tokenEnhancers.add(tokenEnhancer()); tokenEnhancers.add(tokenEnhancer());
...@@ -85,22 +90,26 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu ...@@ -85,22 +90,26 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers); tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
endpoints endpoints
.authenticationManager(authenticationManager) .authenticationManager(authenticationManager) //认证管理器(认证账号密码是否正确)
.accessTokenConverter(jwtAccessTokenConverter()) .accessTokenConverter(jwtAccessTokenConverter())
.tokenEnhancer(tokenEnhancerChain) .tokenEnhancer(tokenEnhancerChain)
.userDetailsService(userDetailsService) .userDetailsService(userDetailsService)//密码模式的用户信息管理
// refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true // refresh token有两种使用方式:重复使用(true)、非重复使用(false),默认为true
// 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准 // 1 重复使用:access token过期刷新时, refresh token过期时间未改变,仍以初次生成的时间为准
// 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的 // 2 非重复使用:access token过期刷新时, refresh token过期时间延续,在refresh token有效期内刷新便永不失效达到无需再次登录的目的
.reuseRefreshTokens(true); .reuseRefreshTokens(true);
} }
/**
* 令牌端点的安全约束
* @param security
*/
@Override @Override
public void configure(AuthorizationServerSecurityConfigurer security) { public void configure(AuthorizationServerSecurityConfigurer security) {
security.authenticationEntryPoint(authenticationEntryPoint()).passwordEncoder(new BCryptPasswordEncoder()) security.authenticationEntryPoint(authenticationEntryPoint()).passwordEncoder(new BCryptPasswordEncoder())
.tokenKeyAccess("isAuthenticated()") .tokenKeyAccess("isAuthenticated()") //
.checkTokenAccess("permitAll()") .checkTokenAccess("permitAll()")
.allowFormAuthenticationForClients(); .allowFormAuthenticationForClients();//表达认证,申请令牌
} }
......
...@@ -5,11 +5,14 @@ import org.springframework.context.annotation.Bean; ...@@ -5,11 +5,14 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
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.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
/** /**
...@@ -17,18 +20,28 @@ import org.springframework.security.crypto.password.PasswordEncoder; ...@@ -17,18 +20,28 @@ import org.springframework.security.crypto.password.PasswordEncoder;
*/ */
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@Order(1) @Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 配置用户的安全拦截策略
* @param http
* @throws Exception
*/
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //关闭csrf保护 http.csrf().disable() //关闭csrf保护
.authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() .authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
.and() .and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/getPublicKey","/oauth/logout").permitAll() .antMatchers("/getPublicKey","/oauth/*").permitAll()
.anyRequest().authenticated(); .anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/oauth/logout")
.invalidateHttpSession(true);
} }
/** /**
...@@ -40,6 +53,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -40,6 +53,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
return super.authenticationManagerBean(); return super.authenticationManagerBean();
} }
/**
* 密码加密器
* @return
*/
@Bean @Bean
public PasswordEncoder passwordEncoder() { public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
......
...@@ -51,7 +51,7 @@ public class ResourceServerConfig { ...@@ -51,7 +51,7 @@ public class ResourceServerConfig {
http.oauth2ResourceServer().jwt() http.oauth2ResourceServer().jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter()); .jwtAuthenticationConverter(jwtAuthenticationConverter());
http.authorizeExchange() http.authorizeExchange()
.pathMatchers("/api/oauth/token", "/oauth/token").permitAll() .pathMatchers("/api/oauth/token","/oauth/*","/api/oauth/genKeyPair").permitAll()
.anyExchange().access(authorizationManager) .anyExchange().access(authorizationManager)
.and() .and()
.exceptionHandling() .exceptionHandling()
......
...@@ -64,40 +64,40 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author ...@@ -64,40 +64,40 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
} }
// // 从缓存取资源权限角色关系列表 // 从缓存取资源权限角色关系列表
// Map<Object, Object> permissionRoles = redisTemplate.opsForHash().entries(AuthConstants.PERMISSION_ROLES_KEY); Map<Object, Object> permissionRoles = redisTemplate.opsForHash().entries(AuthConstants.PERMISSION_ROLES_KEY);
// Iterator<Object> iterator = permissionRoles.keySet().iterator(); Iterator<Object> iterator = permissionRoles.keySet().iterator();
// // 请求路径匹配到的资源需要的角色权限集合authorities统计 // 请求路径匹配到的资源需要的角色权限集合authorities统计
// Set<String> authorities = new HashSet<>(); Set<String> authorities = new HashSet<>();
// while (iterator.hasNext()) { while (iterator.hasNext()) {
// String pattern = (String) iterator.next(); String pattern = (String) iterator.next();
// if (pathMatcher.match(pattern, path)) { if (pathMatcher.match(pattern, path)) {
// authorities.addAll(Convert.toList(String.class, permissionRoles.get(pattern))); authorities.addAll(Convert.toList(String.class, permissionRoles.get(pattern)));
// } }
// } }
// log.info("require authorities:{}", authorities); log.info("require authorities:{}", authorities);
//认证通过且角色匹配的用户可访问当前路径 // 认证通过且角色匹配的用户可访问当前路径
return mono.map(auth -> { // return mono.map(auth -> {
return new AuthorizationDecision(true); // return new AuthorizationDecision(true);
}).defaultIfEmpty(new AuthorizationDecision(false)); // }).defaultIfEmpty(new AuthorizationDecision(false));
// return mono return mono
// .filter(Authentication::isAuthenticated) .filter(Authentication::isAuthenticated)
// .flatMapIterable(Authentication::getAuthorities) .flatMapIterable(Authentication::getAuthorities)
// .map(GrantedAuthority::getAuthority) .map(GrantedAuthority::getAuthority)
// .any(roleId -> { .any(roleId -> {
// // roleId是请求用户的角色(格式:ROLE_{roleId}),authorities是请求资源所需要角色的集合 // roleId是请求用户的角色(格式:ROLE_{roleId}),authorities是请求资源所需要角色的集合
// log.info("访问路径:{}", path); log.info("访问路径:{}", path);
// log.info("用户角色信息:{}", roleId); log.info("用户角色信息:{}", roleId);
// log.info("资源需要权限authorities:{}", authorities); log.info("资源需要权限authorities:{}", authorities);
// //如果是管理员 直接放行 //如果是管理员 直接放行
// if ("ROLE_0".equals(roleId)) { if ("ROLE_0".equals(roleId)) {
// return true; return true;
// } }
// return authorities.contains(roleId); return authorities.contains(roleId);
// }) })
// .map(AuthorizationDecision::new) .map(AuthorizationDecision::new)
// .defaultIfEmpty(new AuthorizationDecision(false)); .defaultIfEmpty(new AuthorizationDecision(false));
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment