Spring Security 4 Rest API
来源:互联网 发布:端口攻击 编辑:程序博客网 时间:2024/06/07 22:44
有霾走遍天下,无霾寸步难行
最近在用spring boot 注解方式 实现 rest 风格的 angular 2 API, 有坑,虽记录之,如下:
Spring Security
是spring出的一套集认证与授权一体的库。官方文档大部分都是以网页提交表单的方式说明的。
Spring Security 认证源码
- Spring Security 4 认证代码在
UsernamePasswordAuthenticationFilter
过滤器中,此过滤器继承AbstractAuthenticationProcessingFilter
,UsernamePasswordAuthenticationFilter
过滤器官方源码:
package org.springframework.security.web.authentication;import org.springframework.security.authentication.AuthenticationServiceException;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import org.springframework.util.Assert;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { /* 用户名 举个使用栗子:<form><input name="username"></form> */ public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; /* 密码 举个使用栗子:<form><input name="password"></form> */ public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password"; private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY; private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; /* 登录只允许POST提交 */ private boolean postOnly = true; /* 添加 /login 登录访问 */ public UsernamePasswordAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); } /* 认证用户帐号和密码 */ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } protected String obtainPassword(HttpServletRequest request) { return request.getParameter(passwordParameter); } protected String obtainUsername(HttpServletRequest request) { return request.getParameter(usernameParameter); } protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } public void setUsernameParameter(String usernameParameter) { Assert.hasText(usernameParameter, "Username parameter must not be empty or null"); this.usernameParameter = usernameParameter; } public void setPasswordParameter(String passwordParameter) { Assert.hasText(passwordParameter, "Password parameter must not be empty or null"); this.passwordParameter = passwordParameter; } public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; } public final String getUsernameParameter() { return usernameParameter; } public final String getPasswordParameter() { return passwordParameter; }}
- 如果需要自定义认证(本例子不需要重写),需重写
UsernamePasswordAuthenticationFilter
过滤器,
并在WebSecurityConfiguration.configure(HttpSecurity http){}
方法中添加此过滤器。源码往下看
解决跨域问题,一个CSRF和另一个CORS
- CSRF(Cross-Site Request Forgery,跨站点伪造请求)
- CORS (Cross Origin Resourse-Sharing, 跨域资源共享)
.csrf().disable()
关闭CSRF.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
允许跨域请求资源。.httpBasic()
也是要添加的。
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;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.WebSecurityConfigurerAdapter;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.web.access.channel.ChannelProcessingFilter;import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration@EnableWebSecuritypublic class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .httpBasic() .and() .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class) .addFilterBefore(new MyUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .authorizeRequests() .antMatchers("/cnvd/list/1").authenticated() .anyRequest().permitAll() .and() .formLogin() .successHandler(new MyAuthenticationSuccessHandler()) .failureHandler(new MyAuthenticationFailureHandler()) .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); }}
CORSFilter
过滤器
import javax.servlet.*;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class CORSFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control"); chain.doFilter(request, response); } @Override public void destroy() { }}
认证之后返回JSON数据,而非重定向(Redirect)
- 实现
AuthenticationSuccessHandler
和AuthenticationFailureHandler
- 在
WebSecurityConfiguration.configure(HttpSecurity http){}
方法中启用。参考:WebSecurityConfiguration
类
AuthenticationSuccessHandler
源码
import org.springframework.context.annotation.Configuration;import org.springframework.security.core.Authentication;import org.springframework.security.web.WebAttributes;import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import org.springframework.security.web.savedrequest.HttpSessionRequestCache;import org.springframework.security.web.savedrequest.RequestCache;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler{ private RequestCache requestCache = new HttpSessionRequestCache(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { PrintWriter writer; String returnStr = "{\"message\":\"sucess\"}"; response.setStatus(200); writer = response.getWriter(); writer.write(returnStr); writer.flush(); writer.close(); requestCache.removeRequest(request, response); clearAuthenticationAttributes(request); } protected final void clearAuthenticationAttributes(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); } public void setRequestCache(RequestCache requestCache) { this.requestCache = requestCache; }}
AuthenticationFailureHandler
源码
import org.springframework.context.annotation.Configuration;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.AuthenticationFailureHandler;import org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler;import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { PrintWriter writer; String returnStr = "{exception:{name:'" + exception.getClass() + "',message:'" + exception.getMessage() + "'}}"; System.out.println(this.getClass().toString()+":"+returnStr); writer = response.getWriter(); writer.write(returnStr); writer.flush(); writer.close(); }}
Spring Security 授权
稍后更新
这里有个结语
CORSFilter
有个注解的写法corsConfigurer()
函数相关,但是对Spring Security默认的 /login 无效,其他自定义Controller请求可以。- 有关CSRF和CORS可以参考:http://www.cnblogs.com/lailailai/p/4528092.html
0 0
- Spring Security 4 Rest API
- 【转】Spring+Spring Security+OAuth2实现REST API权限控制
- Spring+Spring Security+OAuth2实现REST API权限控制
- 使用JWT和Spring Security保护REST API
- 使用JWT和Spring Security保护REST API
- 使用JWT和Spring Security保护REST API
- 使用JWT和Spring Security保护REST API
- 重拾后端之Spring Boot(四):使用JWT和Spring Security保护REST API
- 重拾后端之Spring Boot(四):使用JWT和Spring Security保护REST API
- spring3.0 MVC初步4-spring security REST
- Spring REST API整理
- spring-security api
- spring security for rest web service
- Spring Security开发安全的REST服务
- Spring Security开发安全的REST服务
- spring mvc 创建 rest api
- 学习spring 3.0 security和MVC REST遇到的几个问题
- Spring Security开发安全的REST服务 视频教程
- linux 进程环境
- caffe学习(9)LeNet在Caffe上的使用
- Echarts图表数据动态单位显示
- Android百度地图导航出现无法起调问题的解决方法
- Activity跳转到 TabActivity的子页面
- Spring Security 4 Rest API
- ssh整合问题
- 在其他类中获取屏幕宽高
- hive sql 优化
- SSH中jsp页面提交Form表单值到XxxAction
- openstack--nova help
- 云主机不能外网ssh连接,只能内网ssh连接的问题处理
- ADB 相关
- rabbitmq相关