Spring Security深入浅出--1、基于restful的基本实现

目录

一、Spring Security基本原理

二、security的简单实现

三、个性化认证流程

自定义登陆界面

自定义登陆成功和失败处理


一、Spring Security基本原理

简单来说Spring Security就是一个过滤器链,对于蓝色的过滤器我们可以修改和添加,其他颜色的过滤器链是默认的无法修改

断点验证

具体停留就不截图了,在访问的时候,例如请求路径是/user,首先它进入的是FilterSecurityInterceptor,验证发现没有填写用户信息和名字,就会抛出异常被ExceptionTranslationFilter捕获进入到beforeInvocation()方法中

接着前台就会进入到登陆界面,输入用户和密码,点击登陆之后它会向后台发送/login的请求并且进入到

UsernamePasswordAuthenticationFilter类中进行验证用户和密码。验证完毕之后进入到try方法

执行我们requestmapping

最后将信息返回给前台

二、security的简单实现

创建MyUserDetailsService类继承UserDetailsService

@Component
public class MyUserDetailsService implements UserDetailsService, SocialUserDetailsService {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private PasswordEncoder passwordEncoder;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.core.userdetails.UserDetailsService#
	 * loadUserByUsername(java.lang.String)
	 */
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		logger.info("表单登录用户名:" + username);
		return buildUser(username);
	}

	@Override
	public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
		logger.info("设计登录用户Id:" + userId);
		return buildUser(userId);
	}

	private SocialUserDetails buildUser(String userId) {
		// 根据用户名查找用户信息
		//根据查找到的用户信息判断用户是否被冻结
                //“123456”是在数据库中查询到的密码
		String password = passwordEncoder.encode("123456");
		logger.info("数据库密码是:"+password);
		return new SocialUser(userId, password,
				true, true, true, true,
				AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
	}

}

对于SocialUser()中四个boolean值得说明,SocialUser是User类的实现,如果为true,isEnabled()账号未被删除,isAccountNonExpired()账号没有过期,isAccountNonLocked()账号没有被锁,isCredentialsNonExpired()身份认证没有过期

PasswordEncoder接口中,encode方法是在你从数据库中查到未加密的密码对其进行加密,matches()方法是Security底层自动调用来对比输入的密码是否与数据库的一致

三、个性化认证流程

自定义登陆界面

我们要处理的是如何解决当前端发送过来的是restful请求的时候返回的是状态码和json数据,当请求的是html页面的时候,返回的是HTML页面。

判断授权形式

自定义登陆成功和失败处理

由于前后端分离的原因,登陆成功和登陆失败处理返回的不是html页面而是json数据,所以我们得自定义登陆成功和失败处理

@Component("imoocAuthenticationSuccessHandler")
public class ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SecurityProperties securityProperties;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.web.authentication.
	 * AuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * org.springframework.security.core.Authentication)
	 */
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {

		logger.info("登录成功");

		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {  //如果登陆类型要求返回json就执行以下操作,否则执行else返回html
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(authentication));
		} else {
			super.onAuthenticationSuccess(request, response, authentication);
		}

	}

}
@Component("imoocAuthenctiationFailureHandler")
public class ImoocAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private ObjectMapper objectMapper;
	
	@Autowired
	private SecurityProperties securityProperties;

	
	/* (non-Javadoc)
	 * @see org.springframework.security.web.authentication.AuthenticationFailureHandler#onAuthenticationFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException)
	 */
	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		
		logger.info("登录失败");
		
		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage())));
		}else{
			super.onAuthenticationFailure(request, response, exception);
		}
		
		
	}

}

说明:对于securityProperties.getBrowser().getLoginType()需要自己去定义,这样也就可以实现代码重用

发布了469 篇原创文章 · 获赞 94 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_37909508/article/details/103889538