简单的SpringSecurity项目


基于b站一个视频自己手打的SpringSecurity项目

pom.xml

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
    	<groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <form action="/login" method="post">
        用户名:<input type="text" name="username" /></br>
        密码: <input type="password" name="password" /></br>
        <button type="submit" value="登录"/>
    </form>
</body>
</html>

loginController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class loginController {

//        @RequestMapping("/login")
//        public String login(){
//            return "redirect:main.html";
//        }

        @RequestMapping("/toMain")
        public String toMain(){
          return "redirect:main.html";
        }
        @RequestMapping("/toError")
        public String toError(){
            return "redirect:error.html";
        }
}


main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
    <h3>登录成功</h3>
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>main</title>
</head>
<body>
   登录失败,请重新登录<a href="login.html">跳转</a>
</body>
</html>

在测试类中测试Password(可跳过)

 @Test
    public void testPw(){
        PasswordEncoder psw = new BCryptPasswordEncoder();
        String encode = psw.encode("123456");//将明文密码“123456”进行加密
        System.out.println(encode);//$2a$10$GVUOkD714k6DKhDfR7EIjOwxUQ0yuqfk8iygPx6i4ZCmFkq6YH0WO

        boolean matches = psw.matches("123456", encode);//比较明文密码和加密后的密码
        System.out.println(matches);//true
    }

SecurityConfig.java

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;

/**
 * security配置类
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyAccessDeniedHandler handler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单登录
        http.formLogin()
                .loginPage("/login.html")//自定义登录界面
                .loginProcessingUrl("/login")//自定义登录逻辑
                .successForwardUrl("/toMain")//登录成功后跳转界面,必须是POST方式
//                .successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                .failureForwardUrl("/toError");//登录失败后跳转界面,必须是POST方式
//                .failureHandler(new MyAuthenticationFailureHandler("error.html"));

        //异常处理
        http.exceptionHandling()
                .accessDeniedHandler(handler);


        //授权
        http.authorizeRequests()
                //将login页面放行
                .antMatchers("/login.html").permitAll()
                //将error页面放行
                .antMatchers("/error.html").permitAll()
                .antMatchers("/image/**").permitAll()
//                .antMatchers("/main1.html").hasAuthority("admin")
//                .antMatchers("/main1.html").hasRole("abc")
                //使所有界面都必须被认证,即需要先进行登录
               .anyRequest().authenticated();
                //自动判断登录的角色(authentication)是否有进入某地址(request)的权限,需要先创建下面的MyService类和MyServiceImpl类
                //.anyRequest().access("@myServiceImpl.hasPermsion(request,authentication)");

        //关闭csrf防护
        http.csrf().disable();
    }

    @Bean
    public PasswordEncoder psw(){
        return new BCryptPasswordEncoder();
    }
}


UserServiceImpl.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    private PasswordEncoder psw;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //校验用户名,实际操作中需将用户名和数据库中的用户名进行比较
        if(!"admin".equals(username)){
            throw new UsernameNotFoundException("用户名错误");
        }
        //根据用户名校验密码
        String password = psw.encode("123456");
        //返回用户对象
        return new User("admin",password, AuthorityUtils.createAuthorityList("admin,normal,/main.html"));//给用户创建两个权限:admin和normal
    }
}

MyAuthenticationSuccessHandler.java

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;

@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.setContentType("application/json;charset=utf-8");
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write("{\"status\":\"403\",\"msg\":\"权限不足,请联系管理员\"}");
        writer.flush();
        writer.close();
    }
}

MyAuthenticationSuccessHandler.java


import org.springframework.security.core.Authentication;
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 final String Url;

    public MyAuthenticationSuccessHandler(String url) {
        this.Url = url;
    }



    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
                                        HttpServletResponse httpServletResponse,
                                        Authentication authentication) throws IOException, ServletException {
        httpServletResponse.sendRedirect(Url);
    }
}

MyAuthenticationFailureHandler.java

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 final String Url;

    public MyAuthenticationFailureHandler(String url) {
        this.Url = url;
    }


    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.sendRedirect(Url);
    }
}

MyService.java

import org.springframework.security.core.Authentication;


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

public interface MyService {
    boolean hasPermsion(HttpServletRequest request, Authentication authentication);
}

MyServiceImpl.java

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

@Service
public class MyServiceImpl implements MyService{

    @Override
    public boolean hasPermsion(HttpServletRequest request, Authentication authentication) {
        String uri = request.getRequestURI();//当前登录的uri
        Object principal = authentication.getPrincipal();//拿到当前的用户登录对象
        if(principal instanceof UserDetails){//判断当前登录的用户是不是属于UserDetails对象
            UserDetails userDetails = (UserDetails) principal;//强转
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();//拿到当前登录用户的权限集合
            return authorities.contains(new SimpleGrantedAuthority(uri));
        }
        return false;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值