我已经在restful web服务中实现了Spring Security性。
OAuth访问令牌请求
http://localhost:8084/Weekenter/oauth/token?grant_type=password
作为响应,我将获得访问令牌和刷新令牌。
现在我可以通过以下查询字符串参数使用给定的访问令牌请求API服务method.and完美运行。
请求格式
在上面的快照中,我有JSON
格式的请求,除了access_token
。
{
"mainCategory":"Deals",
"subCategory":"Vigo"
}
事实上,我必须用以下格式来做。
{
"mainCategory":"Deals",
"subCategory":"Vigo",
"access_token":"122356545555"
}
但是,当我尝试这个时,它抛出了一个错误
<oauth>
<error_description>
An Authentication object was not found in the SecurityContext
</error_description>
<error>
unauthorized
</error>
</oauth>
spring-security.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd ">
<!-- This is default url to get a token from OAuth -->
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<!-- <http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>-->
<http pattern="/utililty/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/utililty/getNationalityList" access="ROLE_APP" />
<intercept-url pattern="/utililty/getSettingsUrl" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/admin/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/admin/fetch-sub-category" access="ROLE_APP" />
<intercept-url pattern="/admin/create-category" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- Custom User details service which is provide the user data -->
<bean id="customUserDetailsService"
class="com.weekenter.www.service.impl.CustomUserDetailsService" />
<!-- Authentication manager -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder hash="plaintext">
</password-encoder>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- This defined token store, we have used inmemory tokenstore for now
but this can be changed to a user defined one -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="120" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="restapp"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="restapp" authorities="ROLE_APP" />
</oauth:client-details-service>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
自定义身份验证处理程序
@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private LoginDao loginDao;
public UserDetails loadUserByUsername(String login)
throws UsernameNotFoundException {
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
com.weekenter.www.entity.User user = null;
try {
user = loginDao.getUser(login);
if (user != null) {
if (user.getStatus().equals("1")) {
enabled = false;
}
} else {
throw new UsernameNotFoundException(login + " Not found !");
}
} catch (Exception ex) {
try {
throw new Exception(ex.getMessage());
} catch (Exception ex1) {
}
}
return new User(
user.getEmail(),
user.getPassword(),
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
getAuthorities()
);
}
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authList = getGrantedAuthorities(getRoles());
return authList;
}
public List<String> getRoles() {
List<String> roles = new ArrayList<String>();
roles.add("ROLE_APP");
return roles;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
为什么要使用请求正文传递访问令牌。您需要传递带有标头的令牌。以下是处理访问和刷新令牌的3步过程-
1-获取访问令牌-
http://localhost:8080/webapp/oauth/token?grant_type=password
此请求为您提供访问令牌和刷新令牌。
2-将此访问令牌作为标头传递并访问受保护的资源
http://localhost:8080/webapp/calendar/doctor/search?cityid=1
标题:
授权=持有人f8e5f8cc-9465-4789-8734-9fa97e9fe05a
3-如果以前的令牌过期,则获取新的访问令牌。
http://localhost:8080/webapp/oauth/token?grant_type=refresh_token
让身份验证提供程序如下所示-
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
public class HealthcareUserAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
AppPasswordAuthenticationToken userPassAuthToken;
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
String userName = (String) authentication.getPrincipal();
if (authentication.getCredentials().equals(AppSecurityDAO.getDocUserPassword(userName))) {
userPassAuthToken = new HealthcareUserPasswordAuthenticationToken(authentication.getPrincipal(),
authentication.getCredentials(), grantedAuthorities);
} else if (authentication.getCredentials().equals(AppSecurityDAO.getUserPassword(userName))){
userPassAuthToken = new AppUserPasswordAuthenticationToken(authentication.getPrincipal(),
authentication.getCredentials(), grantedAuthorities);
}else {
throw new BadCredentialsException("Bad User Credentials.");
}
return userPassAuthToken;
}
有如下客户详细服务-
@Service
public class HealthcareClientDetailsService implements ClientDetailsService {
@Autowired
AppSecurityDAO appSecurityDAO;
public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
String clientSecret = appSecurityDAO.getClientOauthSecret(clientId);
if (clientId.equals("client1")) {
List<String> authorizedGrantTypes = new ArrayList<String>();
authorizedGrantTypes.add("password");
authorizedGrantTypes.add("refresh_token");
authorizedGrantTypes.add("client_credentials");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId(clientId);
clientDetails.setClientSecret(clientSecret);
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
return clientDetails;
} else if (clientId.equals("client2")) {
List<String> authorizedGrantTypes = new ArrayList<String>();
authorizedGrantTypes.add("password");
authorizedGrantTypes.add("refresh_token");
authorizedGrantTypes.add("client_credentials");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("client2");
clientDetails.setClientSecret("client2");
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
return clientDetails;
}
else {
throw new NoSuchClientException("No client with requested id: " + clientId);
}
}
并拥有自己的自定义凭证验证,即AppUserPasswordAuthenticationToken,如下所示-
public class AppUserPasswordAuthenticationToken extends AbstractAuthenticationToken { --
private static final long serialVersionUID = 310L;
private final Object principal;
private Object credentials;
private int loginId;
public int getLoginId() {
return loginId;
}
public void setLoginId(int loginId) {
this.loginId = loginId;
}
public AppUserPasswordAuthenticationToken(Object principal, Object credentials) { --
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
public AppUserPasswordAuthenticationToken(Object principal, Object credentials,--
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true);
}
public Object getCredentials() {
return this.credentials;
}
public Object getPrincipal() {
return this.principal;
}
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted");
}
super.setAuthenticated(false);
}
public void eraseCredentials() {
super.eraseCredentials();
this.credentials = null;
}
}
我试图创建spring rest服务,它是由我自己的oauth2资源服务器自动引诱的。我创建了资源服务器: {“error”:“server_error”,“error_description”:“java.io.NotSerializableException:org.springframework.security.crypto.bcrypt.bcryptPasswordenCoder”} 在
我无法获得足够的权限来使用我的应用程序访问Azure Key Vault(而不是通过用户登录)。以下是我的设置: 我已经给了我的名为“keyvault”的应用程序所有的许可。 我的应用程序注册了Azure Active Directory。我已经允许它进入密钥库:
我目前正在学习OAuth 2.0和OpenID Connect,我对授权服务器和访问令牌有疑问。规范将授权服务器定义为: 服务器在成功验证资源所有者并获得授权后向客户端发放访问令牌。 因此,据我所知,客户端将用户重定向到授权服务器,用户在授权服务器上进行身份验证,授权服务器向客户端发出访问令牌。 现在有一件事发生了,直到现在我才明白。有两种可能的方法来理解这一点,我正在努力找到正确的方法: > 授
是否可以使用serviceaccount令牌获得k8s群集访问权限? 我的脚本没有访问kubeconfig文件的权限,但是,它可以访问/var/run/secrets/kubernetes处的服务帐户令牌。io/serviceaccount/token。 以下是我尝试过的步骤,但不起作用。 kubectl配置设置凭据sa用户--令牌=$(cat/var/run/secrets/kubernetes
我正在使用Paypal REST SDK编写PHP代码。我已经设置了我的沙箱帐户使用澳元。当我意识到我最初的交易是以美元进行的,并且交易被冻结后,我就做出了这个决定。 使用我修改过的代码,我正在尝试创建支付--我假设我会得到一个URL,它将允许我重定向用户批准支付。 任何关于这条信息的想法。在澳大利亚,Paypal似乎不支持直接信用卡支付,但我不认为这是问题所在。
我有一个旧项目,后端完全由Firebase处理(我没有专用服务器)。我曾经使用邮递员通过 FCM 将主题消息发送到带有标头授权的endpoint : 错误,当我检查firebase文档时,我知道使用FCM传统HTTP API的应用程序应该考虑迁移到HTTP v1 API 我浏览了文档,它说授权密钥现在看起来像 我被如何为我的项目创建这个授权密钥所困扰,这样我就可以用它来触发使用postman或cu