文档章节

Spring Security 4.2.3 采用 Java Config 实现安全访问控制实例

源子
 源子
发布于 2017/07/12 11:03
字数 1978
阅读 158
收藏 3
点赞 0
评论 5

本文应用Spring Security 4.2.3 ,并采用Java config搭建实例,如果有不对之处望读者指出。

1、pom.xml中引入相关依赖。

<dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>4.2.3.RELEASE</version>
      <scope>compile</scope>
</dependency>
<dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>4.2.3.RELEASE</version>
      <scope>compile</scope>
</dependency>

2、配置DelegatingFilterProxy ,在存放项目配置的包目录下创建一个扩展AbstractSecurityWebApplicationInitializer 的新类即可。

package com.my.security.appconfig;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

@Configuration
public class SpringSecutityInitializer extends AbstractSecurityWebApplicationInitializer {
	
}

3、配置 SecurityConfig类。SecurityConfig类需配置在WebApplicationContext(类似web.xml)中。

package com.my.security.appconfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.my.security.access.config.AccessDeniedHandlerCustom;
import com.my.security.access.config.AuthenticationFailureHandlerCustom;
import com.my.security.access.config.AuthenticationProviderCustom;
import com.my.security.access.config.AuthenticationSuccessHandlerCustom;
import com.my.security.access.config.Http403ForbiddenEntryPointCustom;
import com.my.security.access.config.UserDetailsServiceCustom;
import com.my.security.access.config.UsernamePasswordAuthenticationFilterCustom;

/**
 * 
 * @description Spring security java config
 *
 * @author yuanzi
 * @time 2017年6月13日 下午4:03:37
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //配置自定义的AuthenticationProvider  authenticationProvider通过对比用户输入的登录信息与userDetailsService中获取到的数据库中用户信息确认用户赋权
	@Bean
	public AuthenticationProvider authenticationProvider() {
		AuthenticationProvider authenticationProvider = new AuthenticationProviderCustom(userDetailsService());
		return authenticationProvider;
	}

	//配置自定义的UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter用于过滤用户的登录请求
	@Bean
	public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception {
		UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilterCustom();
		//配置自定义的authenticationSuccessHandler();authenticationFailureHandler();authenticationManager();
		usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
		usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
		usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
		return usernamePasswordAuthenticationFilter;
	}

	//配置自定义的UserDetailsService userDetailsService用于从数据库中或其他途径获取到用户的用户名、密码、权限等信息。
	@Bean
	public UserDetailsService userDetailsService() {
		UserDetailsService userDetailsService = new UserDetailsServiceCustom();
		return userDetailsService;
	}

	//配置自定义的AuthenticationSuccessHandler authenticationSuccessHandler用于返回用户登录成功的结果
	@Bean
	public AuthenticationSuccessHandler authenticationSuccessHandler() {
		AuthenticationSuccessHandler authenticationSuccessHandler = new AuthenticationSuccessHandlerCustom();
		return authenticationSuccessHandler;
	}

	//配置自定义的AuthenticationFailureHandler authenticationFailureHandler用于返回用户登录失败的结果
	@Bean
	public AuthenticationFailureHandler authenticationFailureHandler() {
		AuthenticationFailureHandler authenticationFailureHandler = new AuthenticationFailureHandlerCustom();
		return authenticationFailureHandler;
	}

	//配置自定义的AccessDeniedHandler accessDeniedHandler用于返回用户已通过身份验证,但是访问无权限访问的资源时的结果
	@Bean
	public AccessDeniedHandler accessDeniedHandler() {
		AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerCustom();
		return accessDeniedHandler;
	}

	//配置自定义的Http403ForbiddenEntryPoint http403ForbiddenEntryPoint用于返回用户未通过权限验证的结果
	@Bean
	public Http403ForbiddenEntryPoint http403ForbiddenEntryPoint() {
		Http403ForbiddenEntryPoint http403ForbiddenEntryPoint = new Http403ForbiddenEntryPointCustom();
		return http403ForbiddenEntryPoint;
	}

    //配置AuthenticationManager
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(authenticationProvider());
	}

	//配置需要忽略的一些静态资源等
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/resources/**");
	};

	//配置url权限
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				.antMatchers( "/index.html")
				.permitAll()
				.antMatchers("/userOperation1","/userOperation2")
				.hasRole("USER").anyRequest().authenticated().and();
	    //配置自定义的usernamePasswordAuthenticationFilter();
		http.addFilterAt(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
		//禁用了csrf,默认是不禁用。实际不应禁用。
		http.csrf().disable();
		//配置自定义的accessDeniedHandler();http403ForbiddenEntryPoint();
		http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
		http.exceptionHandling().authenticationEntryPoint(http403ForbiddenEntryPoint());
	}

}

4、参考UsernamePasswordAuthenticationFilter的源码自定义UsernamePasswordAuthenticationFilterCustom类,本例针对多登陆形式,用户名密码登录和用户名验证码登录做了相应代码编写。

package com.my.security.access.config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
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.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.Assert;

import com.my.security.common.utils.EncodeToUserPassWordBySHA;
import com.my.security.database.beans.UserBean;
import com.my.security.database.dao.UserDao;

/**
 * @description 自定义 UsernamePasswordAuthenticationFilter 方法,增加验证码登录的相关内容,编写参考UsernamePasswordAuthenticationFilter源码
 *
 * @author yuanzi
 * @time 2017年6月15日 下午4:39:45
 */
public class UsernamePasswordAuthenticationFilterCustom extends UsernamePasswordAuthenticationFilter {

	private static final Logger log = LogManager.getLogger(UsernamePasswordAuthenticationFilterCustom.class);

	@Autowired
	private UserDao userDao;

	private static final String SPRING_SECURITY_VALIDATE_CODE_KEY = "validateCode";

	private String validateCodeParameter = SPRING_SECURITY_VALIDATE_CODE_KEY;

	public UsernamePasswordAuthenticationFilterCustom() {
		//自定义用户名密码的参数名
		this.setUsernameParameter("phone");
		this.setPasswordParameter("userPass");
		//配置登录过滤路径
		super.setFilterProcessesUrl("/services/login/**");
	}

	//重写attemptAuthentication方法,
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {
		if (!request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
        
		String username = obtainUsername(request) == null ? "" : obtainUsername(request).trim();
		String password = obtainPassword(request) == null ? "" : obtainPassword(request).trim();
		String validateCode = obtainValidateCode(request) == null ? "" : obtainValidateCode(request).trim();

		log.info("username:" + username + "password:" + password + "validateCode:" + validateCode);
		UsernamePasswordAuthenticationToken authRequest = null;
		if (request.getRequestURL().toString().contains("byPassword")) {
			if (username.equals("")) {
			    throw new AuthenticationServiceException("username parameter must not be empty or null!");
			}else if(password.equals("")&&validateCode.equals("")){
			    throw new AuthenticationServiceException("password or validateCode parameter must not be empty or null!");
			}  else {
				UserBean userBean = userDao.findUserInfoByPhone(username);
				if(null==userBean){
					throw new AuthenticationServiceException("user does not exist;");
				}
				String SHAPassword = EncodeToUserPassWordBySHA.encodeToUserPassWord(password, userBean.getSalt());
				authRequest = new UsernamePasswordAuthenticationToken(username + "_PW", SHAPassword);
			}
		} else if (request.getRequestURL().toString().contains("byValidateCode")) {
			authRequest = new UsernamePasswordAuthenticationToken(username + "_VC", validateCode);
		}else{
			throw new AuthenticationServiceException("login method not supported: " + request.getRequestURL().toString());
		}
		
		setDetails(request, authRequest);

		return this.getAuthenticationManager().authenticate(authRequest);

	}

	protected String obtainValidateCode(HttpServletRequest request) {
		return request.getParameter(validateCodeParameter);
	}

	public String getValidateCodeParameter() {
		return validateCodeParameter;
	}

	public void setValidateCodeParameter(String validateCodeParameter) {
		Assert.hasText(validateCodeParameter, "validateCode parameter must not be empty or null");
		this.validateCodeParameter = validateCodeParameter;
	}
}

5、自定义UserDetailsService,用于从数据库、内存或其他途径获取用户的用户名、密码、身份信息。本例从数据库中获取到用户的用户名和密码后直接添加用户身份。

package com.my.security.access.config;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.my.security.database.beans.UserBean;
import com.my.security.database.dao.UserDao;

/**
 * @description userDetailService 获取用户名对应权限
 *
 * @author yuanzi
 * @time 2017年6月16日 下午2:17:27
 */
public class UserDetailsServiceCustom implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
        String userName = username.replace("_PW", "").replace("_VC", "");
        //不同filter的执行顺序不同,authentication中的username在之前UsernamePasswordAuthenticationFilterCustom的代码中加入了后缀,在userDetails的方法被调用的时候,传入的username可能是已经被修改过的。
        UserBean userBean = userDao.findUserInfoByPhone(userName);
        if (null != userBean) {
            SimpleGrantedAuthority auth_app_user = new SimpleGrantedAuthority("ROLE_USER");
            auths.add(auth_app_user);
        }else{
            return null;
        }

        User user = new User(userName, userBean.getUserPass(), true, true, true, true, auths);

        return user;
    }

}

6、自定义AuthenticationProvider,通过对比UsernamePasswordAuthenticationFilter中获取到的用户登录信息与UserDetailsService中查询到的用户信息,确认用户的身份。

package com.my.security.access.config;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.my.common.cache.CacheClient;

/**
 * @description 通过比对登录信息与数据库中信息确认用户身份是否正确
 *
 * @author yuanzi
 * @time 2017年6月19日 下午3:59:37
 */
public class AuthenticationProviderCustom implements AuthenticationProvider {

	private static final Logger log = LogManager.getLogger(AuthenticationProviderCustom.class);

	@Autowired
	private CacheClient<String> client;

	private final UserDetailsService userDetailsService;

	public AuthenticationProviderCustom(UserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {

		log.info("username:" + authentication.getName() + "password:" + String.valueOf(authentication.getCredentials()));
		String[] username_flag = authentication.getName().split("_");
		String username = username_flag[0];
		String flag = username_flag[1];
		String password = String.valueOf(authentication.getCredentials());

		UserDetails userDetails = null;

		if (null != username || "" == username) {
			userDetails = userDetailsService.loadUserByUsername(username);
		}

		if (userDetails == null) {
			throw new UsernameNotFoundException("Invalid username/password");
		} else if (!userDetails.isEnabled()) {
			throw new DisabledException("User is disenabled");
		} else if (!userDetails.isAccountNonExpired()) {
			throw new AccountExpiredException("Account has expired");
		} else if (!userDetails.isAccountNonLocked()) {
			throw new LockedException("Account is locked");
		} else if (!userDetails.isCredentialsNonExpired()) {
			throw new LockedException("Credential is expired");
		}

		String SHAPassword = userDetails.getPassword();

		if (flag.equals("PW")) {
			if (!password.equals(SHAPassword)) {
				throw new BadCredentialsException("password error!");
			}
		} else if (flag.equals("VC")) {
			//从缓存中获取验证码
			String validateCodeInCache = client.get("validateCode" + username);
			if (!validateCodeInCache.equals(password)) {
				throw new BadCredentialsException("validateCode error!");
			}
		}
		return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());

	}

	@Override
	public boolean supports(Class<?> authentication) {
		return UsernamePasswordAuthenticationToken.class.equals(authentication);
	}

}

7、自定义AuthenticationSuccessHandler,使登录成功时返回JSON结果

package com.my.security.access.config;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;

import com.my.security.bussiness.service.UserInformationService;
import com.my.security.database.beans.UserBean;

import net.sf.json.JSONObject;

/**
 * @description 自定义AuthenticationSuccessHandler
 *
 * @author yuanzi
 * @time 2017年07月03日 上午09:39:45
 */
public class AuthenticationSuccessHandlerCustom extends SimpleUrlAuthenticationSuccessHandler {
	@Autowired
	private UserInformationService userInformationService;

	private static final Logger log = LogManager.getLogger(AuthenticationSuccessHandlerCustom.class);
	private JSONObject result = new JSONObject();
	private JSONObject object = new JSONObject();
	private JSONObject data = new JSONObject();

	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
			throws IOException, ServletException {
		result.put("code", 0);
		result.put("info", "login success!");
		UserBean userBean = userInformationService.findUserInfoByPhone(request.getParameter("phone"));
		if (userBean != null) {
			object = JSONObject.fromObject(userBean);
		}
		data.put("result", result);
		data.put("object", object);
		
                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().print(data.toString());
		response.getWriter().flush();

	}

}

8、自定义AuthenticationFailureHandler,使登录失败时返回JSON结果,通过抛出的异常判断是哪种情况造成的失败。

package com.my.security.access.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

import net.sf.json.JSONObject;

/**
 * @description 自定义AuthenticationFailureHandler
 *
 * @author yuanzi
 * @time 2017年07月03日 上午09:40:45
 */
public class AuthenticationFailureHandlerCustom extends SimpleUrlAuthenticationFailureHandler {

	private static final Logger log = LogManager.getLogger(AuthenticationFailureHandlerCustom.class);
	private JSONObject result = new JSONObject();
	private JSONObject object = new JSONObject();
	private JSONObject data = new JSONObject();

	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		result.put("code", 1);
		result.put("info", exception.getMessage());

		data.put("result", result);
		data.put("object", object);

                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().print(data.toString());
		response.getWriter().flush();
	}

}

9、自定义的AccessDeniedHandler Http403ForbiddenEntryPointCustom 方法同上。

package com.my.security.access.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import net.sf.json.JSONObject;

/**
 * @description 自定义AccessDeniedHandler 返回用户访问无权限访问的资源的结果
 *
 * @author yuanzi
 * @time 2017年07月03日 上午09:40:45
 */
public class AccessDeniedHandlerCustom implements AccessDeniedHandler {
	private static final Logger log = LogManager.getLogger(AccessDeniedHandlerCustom.class);

	private JSONObject result = new JSONObject();
	private JSONObject object = new JSONObject();
	private JSONObject data = new JSONObject();

	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException, ServletException {
		result.put("code", 1);
		result.put("info", "Access Denied");

		data.put("result", result);
		data.put("object", object);

                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().print(data.toString());
		response.getWriter().flush();
	}

}
package com.my.security.access.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;

import net.sf.json.JSONObject;

/**
 * @description 自定义Http403ForbiddenEntryPointCustom 返回用户未通过权限验证的结果(例如未登录直接调用接口)
 *
 * @author yuanzi
 * @time 2017年07月03日 上午09:40:45 
 */
public class Http403ForbiddenEntryPointCustom extends Http403ForbiddenEntryPoint {

	private static final Log log = LogFactory.getLog(Http403ForbiddenEntryPointCustom.class);

	private JSONObject result = new JSONObject();
	private JSONObject object = new JSONObject();
	private JSONObject data = new JSONObject();

	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authenticationException) throws IOException, ServletException {
		result.put("code", 1);
		result.put("info", "Access Denied");

		data.put("result", result);
		data.put("object", object);

                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().print(data.toString());
		response.getWriter().flush();
	}
}

 

© 著作权归作者所有

共有 人打赏支持
源子
粉丝 11
博文 28
码字总数 23256
作品 0
朝阳
程序员
加载中

评论(5)

源子
源子

引用来自“爪哇小贩”的评论

自定义认证做的很全,遗憾的是缺少自定义授权部分啊

引用来自“源子”的评论

您所指的缺少的自定义授权部分是?:smiley:

引用来自“爪哇小贩”的评论

就是这部分http.authorizeRequests()
        .antMatchers( "/index.html")
        .permitAll()
        .antMatchers("/userOperation1","/userOperation2")
        .hasRole("USER").anyRequest().authenticated().and();
现在是硬编码,应该到数据库去获得url和角色
:smiley:哦哦~谢谢~我明白了~之后我再补充一下~
爪哇小贩
爪哇小贩

引用来自“爪哇小贩”的评论

自定义认证做的很全,遗憾的是缺少自定义授权部分啊

引用来自“源子”的评论

您所指的缺少的自定义授权部分是?:smiley:
就是这部分http.authorizeRequests()
        .antMatchers( "/index.html")
        .permitAll()
        .antMatchers("/userOperation1","/userOperation2")
        .hasRole("USER").anyRequest().authenticated().and();
现在是硬编码,应该到数据库去获得url和角色
源子
源子

引用来自“爪哇小贩”的评论

自定义认证做的很全,遗憾的是缺少自定义授权部分啊
您所指的缺少的自定义授权部分是?:smiley:
爪哇小贩
爪哇小贩
自定义认证做的很全,遗憾的是缺少自定义授权部分啊
爪哇小贩
爪哇小贩
这是我看到的对spring security讲解最完善清晰的例子,楼主对框架理解很透彻,帮了我大忙,多谢
Spring 和 Django 安全机制的比较

做了一年多的python 方面的web开发工作,昨个有个同学问我Django的安全机制,我是一脸的茫然。每天使用公司开发框架的我,对这些东西了解的甚少,俨然成为一个真正的"码农",只知其然而不知其...

北方攻城师
2014/10/13
0
0
《Spring Security3》第四章第一部分翻译上(数据库管理信息)

第四章 凭证安全存储 到现在为止,我们已经将JBCP Pets站点做了一些用户友好性方面的升级,包括一个自定义的登录页、修改密码以及remember me功能。 在本章中,我们将会把到目前为止都在使用...

heroShane
2014/02/08
0
0
Spring Security 退出

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转...

李玉长
05/05
0
0
java面试必备之ThreadLocal

按照传统的经验,如果某个对象是非线程安全的,在多线程环境下对象的访问需要采用synchronized进行同步。但是模板类并未采用线程同步机制,因为线程同步会降低系统的并发性能,此外代码同步解...

编程老司机
05/16
0
0
Spring Security 学习总结(1)

最近在看Spring Security, 把学习的过程记录一下。 spring security 版本:3.2.7.RELEASE + Java Configuration. Spring Security 是什么? Spring Security 是一个框架,提供比较全面的安全服...

平江夜弹
2015/06/01
0
0
对JDBC的支持 之 7.1 概述

概述 JDBC回顾 传统应用程序开发中,进行JDBC编程是相当痛苦的,如下所示: //cn.javass.spring.chapter7. TraditionalJdbcTest @Test public void test() throws Exception { Connection co...

heroShane
2014/02/27
0
0
spring安全框架Security(二)

好,我们往下看,接着就是应用我们实际项目里的自定义用户权限了 Java代码 security:authentication-manager security:authentication-provider user-service-ref="customUserDetailsServic...

尚浩宇
2015/06/24
0
0
将 Shiro 作为应用的权限基础

Shiro 是 Java 世界中新近出现的权限框架,较之 JAAS 和 Spring Security,Shiro 在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势。本文介绍了 Shiro 的关键概念和权限模型,同时...

heroShane
2014/02/26
0
0
Spring的事务管理难点剖析(4):多线程的困惑

由于Spring的事务管理器是通过线程相关的ThreadLocal来保存数据访问基础设施(也即Connection实例),再结合IoC和AOP实现高级声明式事务的功能,所以Spring的事务天然地和线程有着千丝万缕的...

icheer
2012/07/17
0
0
java电子商务系统源码 Spring MVC+mybatis+spring cloud+spring boot+spring security

鸿鹄云商大型企业分布式互联网电子商务平台,推出PC+微信+APP+云服务的云商平台系统,其中包括B2B、B2C、C2C、O2O、新零售、直播电商等子平台。 分布式、微服务、云架构电子商务平台 java b...

SpringCloud关注者
2017/10/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

MacOS和Linux内核的区别

导读 有些人可能认为MacOS和Linux内核有相似之处,因为它们可以处理类似的命令和类似的软件。甚至有人认为苹果的MacOS是基于linux的。事实上,这两个内核的历史和特性是非常不同的。今天,我...

问题终结者
16分钟前
1
0
SpringBoot | 第八章:统一异常、数据校验处理

前言 在web应用中,请求处理时,出现异常是非常常见的。所以当应用出现各类异常时,进行异常的捕获或者二次处理(比如sql异常正常是不能外抛)是非常必要的,比如在开发对外api服务时,约定了响...

oKong
23分钟前
0
0
mysql高级

一、存储引擎 InnoDB MyISAM 比较 二、数据类型 整型 浮点数 字符串 时间和日期 三、索引 索引分类 索引的优点 索引优化 B-Tree 和 B+Tree 原理 四、查询性能优化 五、切分 垂直切分 水平切分...

丁典
44分钟前
1
0
rsync通过同步服务、系统日志、screen工具

rsync通过后台服务同步 在远程主机中建立一个rsync服务器,在服务器上配置好rsync的各种应用,然后将本机作为rsync的一个客户端连接远程的rsync服务器。 首先在A机器上建立并且配置rsync的配...

黄昏残影
今天
5
0
Spring Cloud Gateway 接口文档聚合实现

在微服务架构下,通常每个微服务都会使用Swagger来管理我们的接口文档,当微服务越来越多,接口查找管理无形中要浪费我们不少时间,毕竟懒是程序员的美德。 由于swagger2暂时不支持webflux 走...

冷冷gg
今天
115
2
流利阅读笔记31-20180720待学习

克罗地亚:输了世界杯,却赢了全世界 雪梨 2018-07-20 1.今日导读 1998 年,年轻的克罗地亚国家队在法国世界杯给全世界留下了不可磨灭的印象,格子军团一举夺得了季军。4 年后,克罗地亚折戟...

aibinxiao
今天
5
0
OSChina 周五乱弹 —— 我们是食物链的最底层

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @温家成 :分享谢安琪的单曲《姿色份子》 《姿色份子》- 谢安琪 手机党少年们想听歌,请使劲儿戳(这里) @贪吃飒:最近p2p怎么了、半个月爆了...

小小编辑
今天
877
14
Android Studio 3.0 之后打包apk出现应用未安装问题

1、废话 出现这个问题的原因,并不是只有一个,而是有多个原因,不懂的估计会被搞得一头雾水,下面我列举的是我遇到的几种问题和网友遇到的几种问题,但不一定是全部,也有可能有些莫名其妙的...

她叫我小渝
今天
0
0
前端基础

1. get请求传参长度的误区 误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。 实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是...

wenxingjun
今天
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部