springboot 整合 springsecurity

导入jar包

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

springsecurity的配置类(依赖于方法上加注解 进行权限验证)第一种 方法

@PreAuthorize("hasAuthority('/user/del')")
package com.liuchao.securitydemo.security.config;

import com.liuchao.securitydemo.security.config.CustomUserDetailsService;
import com.liuchao.securitydemo.security.entity.Menu;
import com.liuchao.securitydemo.security.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法权限控制  @PreAuthorize("hasAuthority('/user/del')")在方法上加上这个可以验证权限
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserMapper userMapper;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws  Exception{
        auth.userDetailsService(customUserDetailsService())//配置用户验证登录的类
                .passwordEncoder(passwordEncoder());//这个是密码校验的类
    }

  //配置校验的路径和不校验的路径
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 所有用户均可访问的资源
                .antMatchers( "/favicon.ico","/css/**","/common/**","/js/**","/images/**","/captcha.jpg","/login","/userLogin","/login-error").permitAll()
                // 任何尚未匹配的URL只需要验证用户即可访问
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").successForwardUrl("/index").failureForwardUrl("/login?error=1")
                .and()
                //权限拒绝的页面
                .exceptionHandling().accessDeniedPage("/403");

        http.logout().logoutSuccessUrl("/login");
   /*     List<Menu> allMenu = userMapper.findAllMenu();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry expressionInterceptUrlRegistry = http.authorizeRequests();
        for(Menu menu:allMenu){
            expressionInterceptUrlRegistry.antMatchers(menu.getUrl()).hasAnyAuthority(menu.getUrl());
        }
        expressionInterceptUrlRegistry.antMatchers( "/favicon.ico","/css/**","/common/**","/js/**","/images/**","/captcha.jpg","/login","/userLogin","/login-error").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().loginPage("/login").successForwardUrl("/index").failureForwardUrl("/login?error=1")
                .and()
                .exceptionHandling().accessDeniedPage("/403");*/
    }

   /**
     * 设置用户密码的加密方式
     * @return
     */
    @Bean
    public Md5PasswordEncoder passwordEncoder() {//密码校验器并注入spring
        return new Md5PasswordEncoder();

    }

    /**
     * 自定义UserDetailsService,授权
     * @return
     */
    @Bean
    public CustomUserDetailsService customUserDetailsService(){//校验用户登录的类交注入spring
        return new CustomUserDetailsService();
    }


    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }



}

springsecurity的配置类(依赖于配置进行权限验证)第二种方法(可以不用依赖于方法上的注解 来进行权限验证)

package com.liuchao.securitydemo.security.config;

import com.liuchao.securitydemo.security.config.CustomUserDetailsService;
import com.liuchao.securitydemo.security.entity.Menu;
import com.liuchao.securitydemo.security.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法权限控制  @PreAuthorize("hasAuthority('/user/del')")在方法上加上这个可以验证权限
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserMapper userMapper;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws  Exception{
        auth.userDetailsService(customUserDetailsService())
                .passwordEncoder(passwordEncoder());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
       /* http.authorizeRequests()
                // 所有用户均可访问的资源
                .antMatchers( "/favicon.ico","/css/**","/common/**","/js/**","/images/**","/captcha.jpg","/login","/userLogin","/login-error").permitAll()
                // 任何尚未匹配的URL只需要验证用户即可访问
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login").successForwardUrl("/index").failureForwardUrl("/login?error=1")
                .and()
                //权限拒绝的页面
                .exceptionHandling().accessDeniedPage("/403");

        http.logout().logoutSuccessUrl("/login");*/
       List<Menu> allMenu = userMapper.findAllMenu();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry expressionInterceptUrlRegistry = http.authorizeRequests();
        for(Menu menu:allMenu){
            expressionInterceptUrlRegistry.antMatchers(menu.getUrl()).hasAnyAuthority(menu.getUrl());//给每个地址进行授权只有有这个权限的才能访问
        }
        expressionInterceptUrlRegistry.antMatchers( "/favicon.ico","/css/**","/common/**","/js/**","/images/**","/captcha.jpg","/login","/userLogin","/login-error").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().loginPage("/login").successForwardUrl("/index").failureForwardUrl("/login?error=1")
                .and()
                .exceptionHandling().accessDeniedPage("/403");
        http.logout().logoutSuccessUrl("/login");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    /**
     * 设置用户密码的加密方式
     * @return
     */
    @Bean
    public Md5PasswordEncoder passwordEncoder() {
        return new Md5PasswordEncoder();

    }

    /**
     * 自定义UserDetailsService,授权
     * @return
     */
    @Bean
    public CustomUserDetailsService customUserDetailsService(){
        return new CustomUserDetailsService();
    }


    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }



}

验证用户登录的类

package com.liuchao.securitydemo.security.config;

import com.liuchao.securitydemo.security.entity.Menu;
import com.liuchao.securitydemo.security.entity.User;
import com.liuchao.securitydemo.security.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

//@Component
public class CustomUserDetailsService implements UserDetailsService {

    @Resource
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userMapper.findByName(s);
        if(StringUtils.isEmpty(user)){
            throw new UsernameNotFoundException("账号不存在");
        }

        List<Menu> menuList = userMapper.findByUserId(user.getId());
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            for(Menu menu: menuList){
                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(menu.getUrl());
                //此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
                grantedAuthorities.add(grantedAuthority);

           }
        user.setAuthorities(grantedAuthorities);//给用户授权

        return user;
    }
}

用户的实体类必需要实现一个UserDetails类

package com.liuchao.securitydemo.security.entity;

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

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;

public class User  implements UserDetails,Serializable {
    private static final long serialVersionUID = -962358173215433342L;
    private Integer id;
    private String username;
    private String nickname;
    private String admin;
    private Date createDate;
    private String password;

    private List<? extends GrantedAuthority> authorities;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getAdmin() {
        return admin;
    }

    public void setAdmin(String admin) {
        this.admin = admin;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setAuthorities(List<? extends GrantedAuthority> authorities) {
        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;
    }
}

密码校验器

package com.liuchao.securitydemo.security.config;

import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * 自定义密码比较器 3
 * 在此 密码我就不加密了
 */
public class Md5PasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }


    @Override
    public boolean matches(CharSequence charSequence, String s) {

        return s.equals(charSequence);
    }
}

springSecurity的获取用户 判断权限的一个工具类

package com.liuchao.securitydemo.security.util;

import com.liuchao.securitydemo.security.entity.User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;

import java.util.Collection;

public class SecurityUtils {
    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }


    public static Collection<? extends GrantedAuthority> getAllPermission(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        return authorities;
    }
  //判断是否有权限
    public static boolean hasPermission(String permission){
        if(StringUtils.isEmpty(permission)){
            return false;
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        boolean hasPermission = false;
        for(GrantedAuthority grantedAuthority : authorities){
            String authority = grantedAuthority.getAuthority();
            if(authority.equals(permission)){
                hasPermission =true;
            }
        }
        return hasPermission;
    }

  //或取当前登录的用户信息
    public static User getUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return (User) authentication.getPrincipal();
    }


    public static void logout(){
        SecurityContextHolder.clearContext();
    }

}

登录

 
 
package com.liuchao.securitydemo.security.controller;

import com.liuchao.securitydemo.security.entity.User;
import com.liuchao.securitydemo.security.exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class LoginController {

@Autowired
private AuthenticationManager authenticationManager;

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

@RequestMapping("/userLogin")
public String userLogin(@RequestParam("username")String userName,
@RequestParam("password")String password,
HttpServletRequest request) throws MyException {
if(StringUtils.isEmpty(userName)){
throw new MyException("没有输入用户名");
}
if(StringUtils.isEmpty(password)){
throw new MyException("没有输入密码");
}
User user=new User();
user.setUsername(userName);
user.setPassword(password);

UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=new UsernamePasswordAuthenticationToken(userName,password);
try{
        //拦截走springsecurity的登录和授权
Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authenticate);
HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); // 这个非常重要,否则验证后将无法登陆
}catch (Exception e){
e.printStackTrace();
return "redirect:login-error?error=2";
}
return "redirect:index";
}
}
 

配置错误页面

@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
    private static final Logger logger = LoggerFactory.getLogger(ErrorPageConfig.class);

    @Override
    public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
        //1、按错误的类型显示错误的网页
//        错误类型为404,找不到网页的,默认显示404.html网页
        ErrorPage e404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404");
        //错误类型为500,表示服务器响应错误,默认显示500.html网页
        ErrorPage e500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500");
        ErrorPage e403 = new ErrorPage(HttpStatus.FORBIDDEN, "/403");
        errorPageRegistry.addErrorPages(e404, e500,e403);
    }

}
package com.liuchao.securitydemo.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {


    @RequestMapping(value="/index")
    public String index()  {
        return "index";
    }

    @RequestMapping(value="/login-error")
    public String loginError(String error)  {
        if("1".equals(error)){
            return  "login-error1";
        }
        return "login-error2";
    }

    @RequestMapping("/404")
    public String to404()  {
        return "404";
    }
    @RequestMapping("/403")
    public String to403()  {
        return "403";
    }
    @RequestMapping("/500")
    public String to500()  {
        return "500";
    }
}

接口增删改查的实例页面

package com.liuchao.securitydemo.security.controller;

import com.liuchao.securitydemo.security.entity.User;
import com.liuchao.securitydemo.security.mapper.UserMapper;
import com.liuchao.securitydemo.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
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;

import java.util.HashMap;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping(value = "/list")
    @PreAuthorize("hasAuthority('/user/list')")
    @ResponseBody
    public List login() {
        List<User> list =  userMapper.getAllUsers();
        return list;
    }

    @RequestMapping(value = "/update")
    @PreAuthorize("hasAuthority('/user/update')")
    @ResponseBody
    public HashMap<String, Object> update() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("state","success");
        return map;
    }


    @RequestMapping(value = "/del")
    @PreAuthorize("hasAuthority('/user/del')")
    @ResponseBody
    public HashMap<String, Object> del() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("state","success");
        return map;
    }
    @RequestMapping(value = "/add")
    @PreAuthorize("hasAuthority('/user/add')")
    @ResponseBody
    public HashMap<String, Object> add() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("state","success");
        return map;
    }

    @RequestMapping(value = "/logout")
    public String logout() {
        SecurityUtils.logout();
        return "redirect:login";
    }

    @RequestMapping(value = "/info")
    @ResponseBody
    public User info() {
        return SecurityUtils.getUser();
    }
}

猜你喜欢

转载自www.cnblogs.com/dkws/p/12156471.html