`
raymond.chen
  • 浏览: 1418613 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

在Springboot2中整合Spring Security安全框架

阅读更多

Spring Security框架

为基于Spring的企业应用系统提供声明式的安全訪问控制解决方式的安全框架,应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。

 

1、创建pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.seasy</groupId>
  <artifactId>springmvc-test</artifactId>
  <version>1.0.0</version>
  <packaging>war</packaging>
  
  <parent>
  	<groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>2.0.8.RELEASE</version> 
  </parent>

  <properties>
  		<java.version>1.8</java.version>
    	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <dependencies>
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- spring security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
	<!-- 解析jsp文件:Springboot内嵌的Tomcat默认不支持jsp -->
	<dependency>
	    <groupId>org.apache.tomcat.embed</groupId>
	    <artifactId>tomcat-embed-jasper</artifactId>
	</dependency>
	<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>jstl</artifactId>
	</dependency>
	<dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
	<dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
    </dependency>
  </dependencies>
  
  <build>
    <finalName>springboot-test</finalName>
  </build>
</project>

 

2、创建UserDetails实现类

public class UserDetailsImpl implements UserDetails {
	private String username;
	private String password;
	private List<GrantedAuthority> authorities = new ArrayList<>();
	
	public UserDetailsImpl(String username, String password, 
			List<GrantedAuthority> authorities){
		this.username = username;
		this.password = password;
		this.authorities = authorities;
	}
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}

	@Override
	public String getPassword() {
		return password;
	}

	@Override
	public String getUsername() {
		return username;
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

 

3、创建UserDetailsService实现类

@Component
public class UserDetailsServiceImpl implements UserDetailsService {
	/**
	 * 根据用户名获取对应的用户信息
	 */
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		String password = username;
        
		UserDetailsImpl user 
			= new UserDetailsImpl(username, password, 
					AuthorityUtils.commaSeparatedStringToAuthorityList(username));
		
		return user;
	}	
}

 

4、创建AuthenticationProvider实现类

@Component
public class DefaultAuthenticationProvider implements AuthenticationProvider {
	@Autowired
    private UserDetailsService userDetailsService;
	
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		//登录输入的信息
		String username = (String) authentication.getPrincipal();
		String password = (String) authentication.getCredentials();
		
		//用户信息合法性认证
		UserDetailsImpl userDetails = (UserDetailsImpl) userDetailsService.loadUserByUsername(username);
        if (userDetails == null) {
              throw new UsernameNotFoundException("用户名不存在");
        }
        
        if (!userDetails.getPassword().equals(password)) {
            throw new BadCredentialsException("密码不正确");
        }
        
        //授权信息
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
        
        return new UsernamePasswordAuthenticationToken(userDetails, password, authorities);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return true;
	}
}

 

5、创建WebSecurityConfigurerAdapter类的子类

@Configuration
@EnableWebSecurity(debug=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
	private static final String LOGIN_PAGE = "/login.jsp";
	private static final String LOGIN_FAILURE_PAGE = "/login.jsp?error=Y";
	
	@Autowired
    private AuthenticationProvider provider;

	@Autowired
	private AccessDeniedHandler accessDeniedHandler;
	
	/**
	 * 认证
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		//添加自定义的认证提供者
		auth.authenticationProvider(provider);
	}
	
	/**
	 * 授权
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//permitAll: 表示不登录也可以访问
		//登录
		http.formLogin()
			.loginPage(LOGIN_PAGE)
			.loginProcessingUrl("/login") //要与登录页面的form表单的action值一致
			.failureUrl(LOGIN_FAILURE_PAGE) //登录失败的回调页面
			.defaultSuccessUrl("/main")
			.permitAll();
			
		//授权
		http.authorizeRequests()
			.antMatchers("/static/**", "/js/**", "/css/**", "/images/**").permitAll()
			.antMatchers("/test/**").hasAnyAuthority("test")
			.antMatchers("/admin/**").hasAnyAuthority("admin") //hasAnyAuthority不需要ROLE_前缀
			.anyRequest()
			.authenticated();
		
		//访问拒绝处理器
		http.exceptionHandling()
			.accessDeniedHandler(accessDeniedHandler);
			
		//退出
		http.logout()
			.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
			.logoutSuccessUrl(LOGIN_PAGE)
			.invalidateHttpSession(true)
			.permitAll();
		
		//关闭 跨域伪造请求限制
		http.csrf().disable();
		
		//关闭 跨域资源共享限制
		http.cors().disable();		
	}
	
	/**
	 * 密码编码器
	 */
	@Bean
	public PasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}
}

 

6、访问拒绝处理器

@Component
public class DefaultAccessDeniedHandler implements AccessDeniedHandler {
	private String error403 = "/WEB-INF/views/error403.jsp";
	
	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException, ServletException {
		if (RequestUtil.isAjaxRequest(request)) {
			response.sendError(403);
		} else if (!response.isCommitted()) {
			if(StringUtil.isNotEmpty(error403)){
				//重定向到错误页面
				request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
				response.setStatus(HttpServletResponse.SC_FORBIDDEN);
				request.getRequestDispatcher(error403).forward(request, response); 
			}else{
				response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
			}
		}
	}
}

 

7、登录页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <h2>自定义登录页面</h2>
    <form action='<c:url value="/login"/>'  method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td colspan="2">
                	<button type="submit">登录</button>
                </td>
            </tr>
        </table>
        
        error=${param.error}<br>
    </form>
</body>
</html>

 

8、403异常页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
    <meta charset="UTF-8">
    <title>error 403</title>
</head>
<body>
	访问出错403:<br>
	
	${requestScope.SPRING_SECURITY_403_EXCEPTION}
</body>
</html>

 

9、登录认证成功后的显示首页

     Controller类

@Controller
public class MainController{
	@GetMapping("/main")
	public String main(){
		return "main";
	}
}

  

    首页main.jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
	首页<br>
	<a href='<c:url value="/logout"/>'>退出</a><br><br>
</body>
</html>

 

10、application.properties属性文件

spring.application.name=springmvc-test

server.port=8888
server.servlet.context-path=/mvctest

#spring mvc
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

 

11、启动类

@SpringBootApplication()
public class Main{
	public static void main(String[] args){
		SpringApplication springApplication = new SpringApplication(Main.class);
		springApplication.run(args);
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics