SecurityConfig:
package com.sdkj.security.oauth.config;
import com.sdkj.security.oauth.handle.MyAccessDeniedHandler;
import com.sdkj.security.oauth.handle.MyAuthenticationFailureHandler;
import com.sdkj.security.oauth.handle.MyAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();
}
@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
//登录成功处理器,不能和failureForwardUrl共存
//请求或页面
.failureHandler(new MyAuthenticationFailureHandler("/error.html"))
//登录成功处理器,不能和successForwardUrl共存
.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
//当发现/login时认为是登录,必须和表单提交的地址一样,接下来才会执行UserDetailsServiceImpl
.loginProcessingUrl("/login")
//自定义登录界面
.loginPage("/login.html");
http.authorizeRequests()
//放行静态资源
.antMatchers("/js/**","/css/**","/images/**").permitAll()
//error.html不需要进行认证
.antMatchers("/error.html").permitAll()
//login.html不需要进行认证
.antMatchers("/login.html").permitAll()
//所有请求都必须被认证,必须登录之后被访问
.anyRequest().authenticated();
//异常处理对象
http.exceptionHandling()
.accessDeniedHandler(myAccessDeniedHandler);
//退出登录
http.logout()
//退出登录跳转页面
.logoutSuccessUrl("/login.html");
//关闭csrf防护
http.csrf().disable();
}
}
TestController:
package com.sdkj.security.oauth.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@RequestMapping("/toMain")
public String toMain()
{
return "redirect:main.html";
}
@RequestMapping("/toError")
public String toError()
{
return "redirect:error.html";
}
@PreAuthorize("hasAuthority('admin1')")
@ResponseBody
@RequestMapping("/cc")
public String cc()
{
return "hello world";
}
}
AuthenticationEvents:
package com.sdkj.security.oauth.handle;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
@Component
public class AuthenticationEvents {
@EventListener
public void onSuccess(AuthenticationSuccessEvent authenticationSuccessEvent){
String username = authenticationSuccessEvent.getAuthentication().getName();
System.out.println("登录成功,用户名:"+username);
}
@EventListener
public void onFailure(AbstractAuthenticationFailureEvent failureDisabledEvent){
String username = failureDisabledEvent.getAuthentication().getName();
System.out.println("登录失败,用户名:"+username);
}
}
MyAccessDeniedHandler:
package com.sdkj.security.oauth.handle;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
//权限不足403处理类
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setHeader("Content-Type","application/json;charset=utf-8");
PrintWriter write = httpServletResponse.getWriter();
write.write("{\"status\":\"error\",\"msg\":\"权限不足,请联系管理员\"}");
write.flush();
write.close();
}
}
MyAuthenticationSuccessHandler:
package com.sdkj.security.oauth.handle;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private String url;
public MyAuthenticationSuccessHandler(String urls) {
url = urls;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
User user = (User) authentication.getPrincipal();
System.out.println("getUsername==>"+user.getUsername());
System.out.println("getAuthorities==>"+user.getAuthorities());
httpServletResponse.sendRedirect(url);
}
}
MyAuthenticationFailureHandler:
package com.sdkj.security.oauth.handle;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
private String url;
public MyAuthenticationFailureHandler(String urls) {
url = urls;
}
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
System.out.println("-->"+httpServletRequest.getAttribute("SPRING_SECURITY_LAST_USERNAME_KEY"));;
System.out.println("-->"+httpServletRequest.getAttribute("SPRING_SECURITY_LAST_USERNAME"));;
httpServletResponse.sendRedirect(url);
}
}
UserDetailServiceImpl:
package com.sdkj.security.oauth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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 org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String password = passwordEncoder.encode("123456");
return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
}
}
SecurityOauthApplication:
package com.sdkj.security.oauth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class SecurityOauthApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityOauthApplication.class, args);
}
}
error.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录失败</title>
</head>
<body>
<div class="login-container">
登录失败
</div>
</body>
</html>
login.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<style>
.login-container {
margin: 50px;
width: 100%;
}
.form-container {
margin: 0px auto;
width: 50%;
text-align: center;
box-shadow: 1px 1px 10px #888888;
height: 300px;
padding: 5px;
}
input {
margin-top: 10px;
width: 350px;
height: 30px;
border-radius: 3px;
border: 1px #E9686B solid;
padding-left: 2px;
}
.btn {
width: 350px;
height: 35px;
line-height: 35px;
cursor: pointer;
margin-top: 20px;
border-radius: 3px;
background-color: #E9686B;
color: white;
border: none;
font-size: 15px;
}
.title{
margin-top: 5px;
font-size: 18px;
color: #E9686B;
}
</style>
<body>
<div class="login-container">
<div class="form-container">
<form class="form-signin" method="post" action="/login">
<h2 class="form-signin-heading">用户登录</h2>
<p>
<label for="username" class="sr-only">用户名</label>
<input type="text" id="username" name="username" class="form-control" placeholder="用户名" required autofocus>
</p>
<p>
<label for="password" class="sr-only">密码</label>
<input type="password" id="password" name="password" class="form-control" placeholder="密码" required>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">登 录</button>
</form>
</div>
</div>
</body>
</html>
main.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
<div class="login-container">
登录成功
</div>
</body>
</html>
pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>