java security 详解_Spring和Security整合详解

Spring和Security整合详解

官方主页

概述

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

Git地址:

Gitee

品茗IT:提供在线快速构建Spring项目工具。

开始搭建

依赖Jar包

org.springframework.security

spring-security-core

${spring.security.version}

org.springframework.security

spring-security-web

${spring.security.version}

org.springframework.security

spring-security-config

${spring.security.version}

Security的安全配置

Spring整合Security需要配置Security的安全控制策略,这里先以form登录控制为例,后面文章会讲token系列。

FormSecurityConfig依赖于其他组件,后面会一一列出:

package com.cff.springwork.security.config;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationDetailsSource;

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.web.authentication.WebAuthenticationDetails;

import com.cff.springwork.security.ajax.AjaxAuthFailHandler;

import com.cff.springwork.security.ajax.AjaxAuthSuccessHandler;

import com.cff.springwork.security.ajax.AjaxLogoutSuccessHandler;

import com.cff.springwork.security.ajax.UnauthorizedEntryPoint;

import com.cff.springwork.security.service.SimpleAuthenticationProvider;

@EnableWebSecurity

public class FormSecurityConfig {

@Configuration

public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Autowired

private SimpleAuthenticationProvider simpleAuthenticationProvider;

@Autowired

@Qualifier("formAuthenticationDetailsSource")

private AuthenticationDetailsSource authenticationDetailsSource;

@Autowired

public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

auth.authenticationProvider(simpleAuthenticationProvider);

}

@Override

public void configure(HttpSecurity http) throws Exception {

http.csrf().disable().exceptionHandling()

.authenticationEntryPoint(new UnauthorizedEntryPoint())

.and().headers()

.frameOptions().disable().and().authorizeRequests()

.antMatchers("/favicon.ico").permitAll()

.antMatchers("/login").permitAll()

.antMatchers("/login.html").permitAll()

.antMatchers("/css/**").permitAll()

.antMatchers("/pub/**").permitAll()

.antMatchers("/user/**").hasAnyRole("USER","ADMIN")

.anyRequest().authenticated()

.and()

.formLogin()

.usernameParameter("userName").passwordParameter("userPwd")

.authenticationDetailsSource(authenticationDetailsSource)

.loginProcessingUrl("/login")

.successHandler(new AjaxAuthSuccessHandler())

.failureHandler(new AjaxAuthFailHandler())

.and()

.logout()

.logoutUrl("/logout").logoutSuccessHandler(new AjaxLogoutSuccessHandler());

}

}

}

Security的校验逻辑

SimpleAuthenticationProvider对form登录校验做了简单的控制:

package com.cff.springwork.security.service;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.authentication.AuthenticationProvider;

import org.springframework.security.authentication.BadCredentialsException;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.stereotype.Component;

import org.springframework.util.StringUtils;

import com.cff.springwork.security.detail.FormAddUserDetails;

import com.cff.springwork.security.detail.FormUserDetails;

@Component

public class SimpleAuthenticationProvider implements AuthenticationProvider {

@Autowired

private FormUserDetailsService formUserDetailsService;

@Override

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

// 验证码等校验

FormAddUserDetails details = (FormAddUserDetails) authentication.getDetails();

System.out.println(details.getToken() + "+++++++++++++++++" + details.getSessionToken());

if (!details.getIsAjax() && !StringUtils.isEmpty(details.getSessionToken())) {

if (!details.getToken().equalsIgnoreCase(details.getSessionToken())) {

throw new BadCredentialsException("验证码错误。");

}

}

// 用户名密码校验

FormUserDetails formUserDetails = (FormUserDetails) formUserDetailsService

.loadUserByUsername(authentication.getName());

System.out.println(authentication.getName() + "+++++++++++++++++" + authentication.getCredentials());

if (!formUserDetails.getUserName().equals(authentication.getName())

|| !formUserDetails.getPassword().equals(authentication.getCredentials())) {

throw new BadCredentialsException("用户名或密码错误。");

}

Collection extends GrantedAuthority> authorities = formUserDetails.getAuthorities();

return new UsernamePasswordAuthenticationToken(formUserDetails.getUsername(), formUserDetails.getPassword(),

authorities);

}

@Override

public boolean supports(Class> arg0) {

return true;

}

}

这里用到了两个实体FormAddUserDetails和FormUserDetails,分别是额外信息处理实体和校验实体,下面会介绍下两个实体。

SimpleAuthenticationProvider控制校验,需要数据库配合查询用户名密码,和前台传过来的用户名密码做对比,因此,需要一个UserDetailsService:

FormUserDetailsService:

package com.cff.springwork.security.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.stereotype.Service;

import com.cff.springwork.model.security.AppUser;

import com.cff.springwork.mybatis.service.AppUserService;

import com.cff.springwork.security.detail.FormUserDetails;

@Service("formUserDetailsService")

public class FormUserDetailsService implements UserDetailsService {

@Autowired

private AppUserService appUserService;

@Override

public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

AppUser user;

try {

user = appUserService.findByName(userName);

} catch (Exception e) {

throw new UsernameNotFoundException("user select fail");

}

if(user == null){

throw new UsernameNotFoundException("no user found");

} else {

try {

return new FormUserDetails(user);

} catch (Exception e) {

throw new UsernameNotFoundException("user role select fail");

}

}

}

}

FormUserDetailsService仅能将用户名密码做校验,如果需要额外的校验信息,需要配置AuthenticationDetailsSource,将HttpServletRequest传递给给WebAuthenticationDetails:

FormAuthenticationDetailsSource:

package com.cff.springwork.security.service;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationDetailsSource;

import org.springframework.security.web.authentication.WebAuthenticationDetails;

import org.springframework.stereotype.Component;

import com.cff.springwork.security.detail.FormAddUserDetails;

@Component("formAuthenticationDetailsSource")

public class FormAuthenticationDetailsSource implements AuthenticationDetailsSource {

@Override

public WebAuthenticationDetails buildDetails(HttpServletRequest context) {

return new FormAddUserDetails(context);

}

}

下面是需要用到的安全实体。

安全控制实体

FormUserDetails负责存储用户名密码和权限相关信息:

package com.cff.springwork.security.detail;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.AuthorityUtils;

import org.springframework.security.core.userdetails.UserDetails;

import com.cff.springwork.model.security.AppUser;

public class FormUserDetails extends AppUser implements UserDetails{

public FormUserDetails(AppUser appUser) {

super(appUser);

}

/**

*

*/

private static final long serialVersionUID = 6272869114201567325L;

@Override

public Collection extends GrantedAuthority> getAuthorities() {

return AuthorityUtils.createAuthorityList("USER");

}

@Override

public String getUserType() {

return super.getUserType();

}

@Override

public String getUsername() {

return super.getUserName();

}

@Override

public boolean isAccountNonExpired() {

return true;

}

@Override

public boolean isAccountNonLocked() {

return true;

}

@Override

public boolean isCredentialsNonExpired() {

return true;

}

@Override

public boolean isEnabled() {

return true;

}

}

AppUser是我自定义的一个实体,是从数据里查询的,这个仅贴出AppUser的代码,查询过程就不写了。

AppUser:

package com.cff.springwork.model.security;

import java.util.UUID;

public class AppUser {

private String uuid;

private String userName;

private String password;

private String userType;

private String userNo;

public AppUser() {

}

public AppUser(String userName, String password) {

this.userName = userName;

this.password = password;

this.uuid = UUID.randomUUID().toString();

this.userType = "1";

}

public AppUser(AppUser appUser) {

this.userName = appUser.userName;

this.password = appUser.password;

this.uuid = appUser.uuid;

this.userType = appUser.userType;

}

public String getUuid() {

return uuid;

}

public void setUuid(String uuid) {

this.uuid = uuid;

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getUserType() {

return userType;

}

public void setUserType(String userType) {

this.userType = userType;

}

public String getUserNo() {

return userNo;

}

public void setUserNo(String userNo) {

this.userNo = userNo;

}

}

FormAddUserDetails是存储一些额外的验证信息,如验证码等。

FormAddUserDetails:

package com.cff.springwork.security.detail;

import java.util.Collection;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.AuthorityUtils;

import org.springframework.security.core.userdetails.UserDetails;

import

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值