- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从各种资源了解 Spring Security,我知道过滤器和身份验证管理器如何分开工作,但我不确定请求与它们一起工作的确切顺序。如果我没记错的话,简而言之,请求首先通过过滤器,然后过滤器调用它们各自的身份验证管理器。
我想允许两种身份验证 - 一种使用 JWT token ,另一种使用用户名和密码。以下是 security.xml
的摘录Security.xml
<http pattern="/api/**" create-session="stateless" realm="protected-apis" authentication-manager-ref="myAuthenticationManager" >
<csrf disabled="true"/>
<http-basic entry-point-ref="apiEntryPoint" />
<intercept-url pattern="/api/my_api/**" requires-channel="any" access="isAuthenticated()" /> <!-- make https only. -->
<custom-filter ref="authenticationTokenProcessingFilter" position = "FORM_LOGIN_FILTER"/>
</http>
<beans:bean id="authenticationTokenProcessingFilter"
class="security.authentication.TokenAuthenticationFilter">
<beans:constructor-arg value="/api/my_api/**" type="java.lang.String"/>
</beans:bean>
<authentication-manager id="myAuthenticationManager">
<authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>
<beans:bean id="myAuthenticationProvider"
class="security.authentication.myAuthenticationProvider" />
MyAuthenticationProvider.java
public class MyAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// Code
}
@Override
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
TokenAuthenticationFilter.java
public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter{
protected TokenAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl); //defaultFilterProcessesUrl - specified in applicationContext.xml.
super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl)); //Authentication will only be initiated for the request url matching this pattern
setAuthenticationManager(new NoOpAuthenticationManager());
setAuthenticationSuccessHandler(new TokenSimpleUrlAuthenticationSuccessHandler());
setAuthenticationFailureHandler(new MyAuthenticationFailureHandler());
}
/**
* Attempt to authenticate request
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException,
IOException,
ServletException {
String tid = request.getHeader("authorization");
logger.info("token found:"+tid);
AbstractAuthenticationToken userAuthenticationToken = authUserByToken(tid,request);
if(userAuthenticationToken == null) throw new AuthenticationServiceException("Invalid Token");
return userAuthenticationToken;
}
/**
* authenticate the user based on token
* @return
*/
private AbstractAuthenticationToken authUserByToken(String token,HttpServletRequest request) throws
JsonProcessingException {
if(token==null) return null;
AbstractAuthenticationToken authToken =null;
boolean isValidToken = validate(token);
if(isValidToken){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
authToken = new UsernamePasswordAuthenticationToken("", token, authorities);
}
else{
BaseError error = new BaseError(401, "UNAUNTHORIZED");
throw new AuthenticationServiceException(error.getStatusMessage());
}
return authToken;
}
private boolean validate(String token) {
if(token.startsWith("TOKEN ")) return true;
return false;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
super.doFilter(req, res, chain);
}
}
通过 myAuthenticationProvider
我想要基于用户名-密码的身份验证 & 通过自定义过滤器我想检查 JWT token 。有人可以告诉我我的方向是否正确吗?
最佳答案
从广义上讲,具有多个 AuthenticationProvider
的要求分为两类:
/web/**
的所有请求进行身份验证;/api/**
的所有请求进行身份验证。每个解决方案都略有不同,但它们都基于一个共同的基础。
Spring Security 对基于表单的用户名-密码身份验证具有开箱即用的支持,因此无论以上两种类别如何,都可以很容易地实现。
然而,基于 token 的身份验证不支持开箱即用,因此需要自定义代码来添加必要的支持。添加此支持需要以下组件:
AbstractAuthenticationToken
的 POJO,它将保存用于身份验证的 token 。AbstractAuthenticationProcessingFilter
的过滤器,它将从请求中提取 token 值并填充在上面第 1 步中创建的 POJO。AuthenticationProvider
实现,它将使用 token 对请求进行身份验证。AbstractAuthenticationToken
POJO 需要保存用于验证请求的 JWT token ,因此,最简单的 AbstractAuthenticationToken
实现可能如下所示:
public JWTAuthenticationToken extends AbstractAuthenticationToken {
private final String token;
JWTAuthenticationToken(final String token, final Object details) {
super(new ArrayList<>());
this.token = token;
setAuthenticated(false);
setDetails(details);
}
@Override
public Object getCredentials() { return null; }
@Override
public String getPrincipal() { return token; }
}
AbstractAuthenticationProcessingFilter
需要一个过滤器来从请求中提取 token 。
public class JWTTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JWTTokenAuthenticationFilter (String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Override
public Authentication attemptAuthentication(final HttpServletRequest request
, final HttpServletResponse response)
throws AuthenticationException {
final JWTAuthenticationToken token = new JWTAuthenticationToken(/* Get token from request */
, authenticationDetailsSource.buildDetails(request));
return getAuthenticationManager().authenticate(token);
}
}
请注意,过滤器不会尝试执行身份验证;相反,它将实际身份验证委托(delegate)给 AuthenticationManager
,这可确保任何前后身份验证步骤也能正确执行。
AuthenticationProvider
AuthenticationProvider
是负责执行身份验证的实际组件。如果配置正确,它会由 AuthenticationManager
自动调用。一个简单的实现如下所示:
public class JWTAuthenticationProvider implements AuthenticationProvider {
@Override
public boolean supports(final Class<?> authentication) {
return (JWTAuthenticationToken.class.isAssignableFrom(authentication));
}
@Override
public Authentication authenticate(final Authentication authentication)
throws AuthenticationException {
final JWTAuthenticationToken token = (JWTAuthenticationToken) authentication;
...
}
}
为每个 URL 系列使用不同的 http
元素,例如:
<bean class="com.domain.path.to.provider.FormAuthenticationProvider" "formAuthenticationProvider" />
<bean class="com.domain.path.to.provider.JWTAuthenticationProvider" "jwtAuthenticationProvider" />
<authentication-manager id="apiAuthenticationManager">
<authentication-provider ref="jwtAuthenticationProvider" />
</authentication-manager>
<authentication-manager id="formAuthenticationManager">
<authentication-provider ref="formAuthenticationProvider" />
</authentication-manager>
<bean class="com.domain.path.to.filter.JWTAuthenticationFilter" id="jwtAuthenticationFilter">
<property name="authenticationManager" ref="apiAuthenticationManager" />
</bean>
<http pattern="/api/**" authentication-manager-red="apiAuthenticationManager">
<security:custom-filter position="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter"/>
...
</http>
<http pattern="/web/**" authentication-manager-red="formAuthenticationManager">
...
</http>
由于不同的 URL 系列需要不同的身份验证模式,我们需要两个不同的 AuthenticationManager
和两个不同的 http
配置,每个 URL 系列一个。对于每一个,我们选择支持哪种身份验证模式。
使用单个 http
元素,如下所示:
<bean class="com.domain.path.to.provider.FormAuthenticationProvider" "formAuthenticationProvider" />
<bean class="com.domain.path.to.provider.JWTAuthenticationProvider" "jwtAuthenticationProvider" />
<authentication-manager id="authenticationManager">
<authentication-provider ref="formAuthenticationProvider" />
<authentication-provider ref="jwtAuthenticationProvider" />
</authentication-manager>
<bean class="com.domain.path.to.filter.JWTAuthenticationFilter" id="jwtAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<http pattern="/**">
<security:custom-filter after="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter"/>
...
</http>
注意以下几点:
AuthenticationManager
不需要为 http
元素明确指定,因为配置中只有一个,它的标识符是 authenticationManager
,即默认值。AuthenticationManager
配置为使用多个 AuthenticationProvider
。这可确保尝试多种身份验证机制,直到找到请求支持的一种。关于java - 如何使用 Spring Security 提供多种身份验证方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49225035/
请帮助我的建议。 我需要通过 xml 文件中的某个变量在我的应用程序上禁用/启用 spring 安全性。 我的 spring-security.xml 文件
我做了很多研究,对我来说一切看起来都是正确的......但我无法让它发挥作用!有人有什么想法吗? 无论我做什么,相关映射仍然对任何人公开(匿名或登录,无论他们具有什么角色)。 理想情况下,我希望所有请
我们正在考虑为我们网站的一部分启用 SSL,但某些页面包含来自第三方供应商(如 Google AdSense)的广告。 我认为这会给我们的用户带来一个恼人的问题,因为他们在查看带有广告的页面时会看到类
我正在开发一个休息服务,它将通过浏览器提供 浏览器单页应用程序和移动应用程序。目前我的服务正在运行 根本没有 Spring 。 oauth2 客户端是在过滤器内部实现的,所以可以说是“手动”。 我正在
我正在为我公司的网站添加 Content-Security-Policy-Report-Only 标题。在我研究它时,我发现一些页面已经设置了 Content-Security-Policy head
在 XML 配置中,我可以使用 security 命名空间来启用对安全性的支持,例如: 我尝试使用没有 XML 的 Spring,只有 @Configuration 类。与上述 XM
我正在使用 Spring Security 3.0.2,但找不到从数据库加载匿名用户角色的方法(我有动态角色,可以将角色分配给每个人)。 我尝试使用自定义的anonymousAuthenticatio
我有那个代码。但是当我在浏览器中进入 app_dev.php/login浏览器说:该页面进行了太多重定向 安全.yml安全: 编码器: Symfony\Component\Security\Core\
我正在使用SSH Secure Shell客户端,这是一个连接服务器的好工具。 但是,我想知道是否可以记录通过SSH Secure Shell客户端运行的程序中所有即将出现的消息。例如:./ test
我有那个代码。但是当我在浏览器中进入 app_dev.php/login浏览器说:该页面进行了太多重定向 安全.yml安全: 编码器: Symfony\Component\Security\Core\
如何为表单例份验证提供程序设置 success_handler(和 failure_handler)? Silex 使用此配置忽略我: register(new Silex\Provider\Secu
新手问题...我已成功实现自定义处理程序和服务(自定义用户详细信息服务、身份验证成功、身份验证失败)并且一切正常。我现在还实现了如果 3 次并发身份验证失败将锁定帐户(一定时间)的功能。 我现在继续处
我正在使用 Spring security java 配置,我想知道一种实现多个 url 注销的方法。即 logout().logoutRequestMatcher(new AntPathReques
我正在为我的 SP 使用 Spring Security SAML 扩展。用户通过 IDP 身份验证后,SP 使用某种方法允许后续调用不必通过 IDP 重新进行身份验证。这是如何在 Spring Se
spring security 有没有办法防止下面的最后一点?我正在使用 3.0.5 - 用户登录我的网站 - 用户转到网站中的任何页面并单击注销 -注销链接使用户 session 无效并将它们发送到
要么我迟到了,要么我做错了什么。我正在使用 Visual Studio 2013,但是我试图使用 Membership 类,using System.Web.Security;我的程序集中不存在命名空
我有一个具有依赖性的oauth2客户端spring-boot应用程序: - Spring 靴1.2.0.RC1 -spring-security-oauth2 2.0.4.RELEASE - Spri
我想在控制台应用程序中生成 HashPasswordForStoringInConfigFile。 它是在 Web 应用程序中使用以下类完成的 System.Web.Security.FormsAut
我需要有多个 PRE_AUTH Spring 安全过滤器。特别是我需要使用 PRE_AUTH除了配置为 PRE_AUTH 的两个过滤器之外的过滤器在 Spring Security 3.0 的 SAM
我猜这里没有答案,但我想知道是否有办法创建这样的自定义注释: @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({E
我是一名优秀的程序员,十分优秀!