栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring-security【2022-3-15更新】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring-security【2022-3-15更新】

话不多说

导包

本质上主要是使用了AOP 和 拦截器!另外还有自定义登录认证成功、失败方法自定义权限不够 403 异常处理方法 模拟前端界面

导包

	org.springframework.boot
	spring-boot-starter-security









WebSecurityConfigurerAdapter:自定义 Security 策略AuthenticationManagerBuilder:自定义认证策略@EnableWebSecurity:开启WebSecuryti模式

Authentication - 认证
Authorization - 授权

Controller.java

package com.example.demo;

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

@Controller
public class MyController {

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

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

本质上主要是使用了AOP 和 拦截器!

SecurityConfiguration.java

package com.example.demo.config;

import com.example.demo.hanlder.MyAccessDeniedHandler;
import com.example.demo.hanlder.MyAuthenticationFailureHandler;
import com.example.demo.hanlder.MyAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    // 下面自定义登录逻辑时需要用到
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 请求授权的规则
        http.authorizeRequests()
                .antMatchers("/login.html").permitAll() // 任何权限都可以访问
                .antMatchers("/error.html").permitAll()

                // 权限判断 UserDetailsServiceImpl
                .antMatchers("/main.html").hasAnyAuthority("admina", "user")

                // 还可以通过ip地址来开放权限
//                .antMatchers("/main.html").hasIpAddress("****")

                // 角色判断 UserDetailsServiceImpl  或者 下面的认证里面设置
//                .antMatchers("/main.html").hasRole("abc")

                // 使用正则表达式放行访问文件
//                .regexMatchers()

                // 放行使用 get 方式访问的资源。
//                .regexMatchers(HttpMethod.GET,"get").permitAll()

                // 主要适用于 servletPath 路径请求的方式
                // servletPath - 在 .properties 中进行配置的项目路径。 -- 一般使用 antMatchers 已经足够了
//                .mvcMatchers("/demo").servletPath("/xxx").permitAll()

                .anyRequest().authenticated(); // 所有请求必须被认证 (必须登录之后被访问)


        
        http.formLogin()
                .loginPage("/login.html")
                .usernameParameter("user")
                .passwordParameter("pwd")
                .loginProcessingUrl("/loogin")
//                .successForwardUrl("/toMain")
//                .failureForwardUrl("/toError");
                .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
                .failureHandler(new MyAuthenticationFailureHandler("/error.html"));

        // 防跨站攻击 关闭csrf功能 - 登录失败的原因
        http.csrf().disable();

        // 开启注销功能 - 删除cookie、之类的... 一般跳到首页或者登录界面
        // logoutSuccessUrl - 注销成功跳转url
//        http.logout().logoutSuccessUrl("/login");

        // 开启记住我功能,cookie  存活时间 2周。 自定义接收参数
//        http.rememberMe().rememberMeParameter("remenber");

        // 异常处理 - 403 权限不够
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);
    }

    // 认证
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//
//        // 密码加密与匹配密码
//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
//        String result = encoder.encode("myPassword");
//        System.out.println(encoder.matches("myPassword", result));
//
//        // 这些用户数据应该从数据库中获取
//        
//        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//                .withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("admin", "user")
//                .and()
//                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("admin");
//    }


}


其中,如果要自定义一个登录逻辑,需要实现一个 UserDetailsService 这个接口UserDetailsServiceImpl.java

package com.example.demo;

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 UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    PasswordEncoder passwordEncoder;

    // 模拟的后端数据
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 这个 username 是表单中的 username  ->  可以通过配置更改为 pwd 等其他
        System.out.println("自定义登录逻辑,前端传参用户名:"+username);

//        User user = userService.findByUserName(username);
//        System.out.println("自定义登录逻辑,获取到的用户:"+user);

        // 1.查询数据库判断用户是否存在,不存在则抛异常 UsernameNotFoundException
        if ("user".equals(username)) {
            // 2.存在用户 -> 获取密码(注册时已经加密过的密码,进行解析) 或者 直接把密码放入构造方法

            String password = passwordEncoder.encode("123");
            // admin 是权限  ROLE_abc 是角色
            return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin, ROLE_abc"));
        } else {
            throw new UsernameNotFoundException("用户不存在");
        }
    }
}

另外还有自定义登录认证成功、失败方法

成功

package com.example.demo.hanlder;

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 url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        System.out.println("自定义登录认证成功处理");
        User user = (User) authentication.getPrincipal();

        System.out.println("登录成功,用户信息:" + user.toString());

        response.sendRedirect(url);
    }
}

失败

package com.example.demo.hanlder;

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 url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        System.out.println("自定义登录认证失败处理");
        response.sendRedirect(url);
    }
}
自定义权限不够 403 异常处理方法
package com.example.demo.hanlder;

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 request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        System.out.println("自定义权限不够,403处理方案");
        // 响应码
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("模拟权限不够界面:权限不够!");
        writer.flush();
    }
}

模拟前端界面

error.html




    
    Title


登录错误界面



login.html




    
    登录页面

    
    



main.html




    
    Title


主界面main



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763341.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号