2019独角兽企业重金招聘Python工程师标准>>>
一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分
用户认证
指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。
一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。
用户授权
指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的
一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限
用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP
表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。
在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control
List,ACL),可以对应用中的领域对象进行细粒度的控制。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
xx.properties
spring.datasource.url=jdbc:mysql://localhost:3306/xx_dev?useSSL=false
spring.datasource.username=xx
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.user_ds.url=jdbc:mysql://localhost:3306/xx_user_dev?useSSL=false
spring.user_ds.username=xx
spring.user_ds.password=123
spring.user_ds.driver-class-name=com.mysql.jdbc.Driver
XXXSceurity.java
@Configuration
@EnableWebSecurity
public class SecurityConf extends WebSecurityConfigurerAdapter{
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
//auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
super.configure(auth);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/zcs/user/register").permitAll()
.antMatchers("/zcs/user/enable").permitAll()
.antMatchers("/zcs/user/disable").permitAll()
// .antMatchers("/zcs/user/register").hasAuthority("ADMIN")
// .antMatchers("/zcs/user/enable").hasAuthority("ADMIN")
// .antMatchers("/zcs/user/disable").hasAuthority("ADMIN")
.antMatchers("/zcs/user/login").hasAuthority("USER")
.antMatchers("/zcs/user/logout").hasAuthority("USER")
.antMatchers("/zcs/admin/login").hasAuthority("ADMIN")
.antMatchers("/zcs/admin/logout").hasAuthority("ADMIN")
.antMatchers("/zcs/**", "/ys/**").hasAnyAuthority("USER","ADMIN")
.antMatchers("/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new AjaxLoginUrlAuthenticationEntryPoint())
.and()
.formLogin()
.loginProcessingUrl("/zcs/user/login")
// .successForwardUrl("/user/loginSuccess")
// .failureForwardUrl("/user/loginFailure")
.successHandler(new AjaxLoginUrlAuthenticationSuccessHandler())
.failureHandler(new AjaxLoginUrlAuthenticationFailureHandler())
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/zcs/user/logout")
.addLogoutHandler(new AjaxLogoutHandler())
// .logoutSuccessUrl("/user/loginSueecess")
// .logoutSuccessHandler(new AjaxLogoutSuccessHandler())
.deleteCookies("remember-me")
.permitAll()
.and()
.rememberMe()
.and()
.csrf()
.disable()
// .and()
// .csrf().requireCsrfProtectionMatcher(
// new AndRequestMatcher(
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs/user/**", HttpMethod.POST.toString())),
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs/user/**", HttpMethod.OPTIONS.toString())),
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs*/**", HttpMethod.GET.toString())),
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs*/**", HttpMethod.HEAD.toString())),
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs*/**", HttpMethod.OPTIONS.toString())),
// new NegatedRequestMatcher(new AntPathRequestMatcher("/zcs*/**", HttpMethod.TRACE.toString()))
// )
// )
// .and()
// .addFilterBefore(new CorsHeaderFilter(), ChannelProcessingFilter.class)
// .addFilterAfter(new CsrfCookieFilter(), CsrfFilter.class)
;
}
public class AjaxAuthenticationData {
private int status;
private String message;
public AjaxAuthenticationData(int status, String message) {
super();
this.status = status;
this.message = message;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
XXXXHandlers
public class AjaxLoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Log logger = LogFactory.getLog(AjaxLoginUrlAuthenticationEntryPoint.class);
/**
* Performs the redirect (or forward) to the login form URL.
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + authException.getMessage());
}
}
public class AjaxLoginUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
ObjectMapper objectMapper = new ObjectMapper();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try {
AuthenticationData json = new AuthenticationData(0, "Ajax auth succeeds!");
objectMapper.writeValue(response.getOutputStream(), json);
} catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Error to write JSON: " + ex.getMessage(), ex);
}
super.onAuthenticationSuccess(request, response, authentication);
}
}
public class AjaxLoginUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
ObjectMapper objectMapper = new ObjectMapper();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try {
AuthenticationData json = new AuthenticationData(1, "Ajax auth failure!");
objectMapper.writeValue(response.getOutputStream(), json);
} catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Error to write JSON: " + ex.getMessage(), ex);
}
// super.onAuthenticationFailure(request, response, exception);
}
}
public class AjaxLogoutHandler extends SecurityContextLogoutHandler {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
ObjectMapper objectMapper = new ObjectMapper();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try {
AuthenticationData json = new AuthenticationData(0, "Ajax auth Logout!");
objectMapper.writeValue(response.getOutputStream(), json);
} catch (IOException ex) {
throw new HttpMessageNotWritableException("Error to write JSON: " + ex.getMessage(), ex);
}
super.logout(request, response, authentication);
}
}
public class AjaxLoginUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
ObjectMapper objectMapper = new ObjectMapper();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try {
AuthenticationData json = new AuthenticationData(0, "Ajax auth succeeds!");
objectMapper.writeValue(response.getOutputStream(), json);
} catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Error to write JSON: " + ex.getMessage(), ex);
}
super.onAuthenticationSuccess(request, response, authentication);
}
}
public class CorsHeaderFilter implements Filter {
public static final String REQUEST_HEADER_NAME = "X-CSRF-TOKEN";
private final List<String> allowedOrigins = Arrays.asList("http://localhost:8080",
"http://127.0.0.1:8080",
"http://192.168.1.53:8080",
"http://cuikexi:8080");
public void destroy() {
//do nothing
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// Access-Control-Allow-Origin
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
response.setHeader("Vary", "Origin");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, " + REQUEST_HEADER_NAME);
}
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
//do nothing
}
}
public class CsrfCookieFilter extends OncePerRequestFilter {
public static final String RESPONSE_COOKIE_NAME = "CSRF-TOKEN";
protected static final String REQUEST_ATTRIBUTE_NAME = "_csrf";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken token = (CsrfToken) request.getAttribute(REQUEST_ATTRIBUTE_NAME);
Cookie cookie = new Cookie(RESPONSE_COOKIE_NAME, token.getToken());
cookie.setPath("/");
response.addCookie(cookie);
filterChain.doFilter(request, response);
}
}
client(js)
var request_data = {'username':'zm','password':'123456'};
$.ajax({
type: "POST",
url: "/zcs/user/login",
data: request_data,
success: function(msg){
alert( "Response Data: " + msg );
}
});
client(curl)
#直接无权访问
#curl -XGET -uzhaomeng:123456 http://127.0.0.1:8080/zcs/input/suggest/list?term=teng
#curl -XGET -uzhaomeng2:123456 http://127.0.0.1:8080/zcs/input/suggest/list?term=teng
#登陆验证
curl -XPOST -d'username=zhaomeng&password=123456' http://127.0.0.1:8080/zcs/user/login
curl -XPOST -d'username=zhaomeng2&password=123456' http://127.0.0.1:8080/zcs/user/login
#直接授权访问
#curl -XGET -uzhaomeng:123456 http://127.0.0.1:8080/zcs/input/suggest/list?term=teng
#curl -XGET -uzhaomeng2:123456 http://127.0.0.1:8080/zcs/input/suggest/list?term=teng
#登出验证
curl -XPOST -d'username=zhaomeng&password=123456' http://127.0.0.1:8080/zcs/user/login
curl -XPOST -d'username=zhaomeng2&password=123456' http://127.0.0.1:8080/zcs/user/login