zoukankan      html  css  js  c++  java
  • SpringBoot2.0整合SpringSecurity实现自定义表单登录

    我们知道企业级权限框架一般有Shiro,Shiro虽然强大,但是却不属于Spring成员之一,接下来我们说说SpringSecurity这款强大的安全框架。费话不多说,直接上干货。

    pom文件引入以下依赖:

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

    首先创建WebConfig继承WebSecurityConfigurerAdapter,实现代码如下:

    
    import com.zaxxer.hikari.HikariDataSource;
    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.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.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
    import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
    import org.springframework.session.FindByIndexNameSessionRepository;
    import org.springframework.session.Session;
    import org.springframework.session.data.redis.RedisOperationsSessionRepository;
    
    /**
     * author:yuxuan
     * date:2018/12/16/016 12:00
     * description 
     */
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private MyAuthenticationSuccessHandler myAuthenticationSuccess;
        @Autowired
        private MyAuthenticationProvider myAuthenticationProvider;
        @Autowired
        private MyAuthenticationFailHandler myAuthenticationFailHandler;
        @Autowired
        private MyUserDetailService myUserDetailService;
        @Autowired
        private HikariDataSource dataSource;
    
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(myAuthenticationProvider);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.headers().frameOptions().sameOrigin();
            http.csrf()
                    .disable()
                    .authorizeRequests()
                    .antMatchers("/static/**","/resources/**","/login/userauth").permitAll()
                    .antMatchers("/health","/autoconfig","/configprops","/beans","/dump","/env","/env/**","/info","/mappings","/metrics","/metrics/**","/shutdown","/trace").hasRole("SYS")
                    .anyRequest().authenticated()
                    .and().formLogin().loginPage("/login")
                    .successHandler(myAuthenticationSuccess)
                    .failureHandler(myAuthenticationFailHandler)
                    .permitAll()
                    .and()
                    .logout().deleteCookies("SESSION", "remember-me")
                    .and().sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true).expiredUrl("/login").and()
                    .and().rememberMe().alwaysRemember(true).tokenRepository(persistentTokenRepository())
                    .tokenValiditySeconds(60 * 60 * 24 * 7)  //设置记住我的时间为7天
                    .userDetailsService(myUserDetailService)//设置userDetailsService
                    ;
            http.headers().cacheControl(); //禁用缓存
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers( "/api/**", "/resources/**", "/static/**", "/public/**", "/webui/**", "/h2-console/**"
                            , "/configuration/**",  "/swagger-resources/**", "/api-docs", "/api-docs/**", "/v2/api-docs/**"
                            ,  "/**/*.css", "/**/*.js","/**/*.ftl", "/**/*.png ", "/**/*.jpg", "/**/*.gif ", "/**/*.svg", "/**/*.ico", "/**/*.ttf", "/**/*.woff");
        }
    
    
    
        @Bean
        public PersistentTokenRepository persistentTokenRepository() {
            JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
            tokenRepository.setDataSource(dataSource);
            return tokenRepository;
        }
    }
    

    以上为SpringSecurity的主要配置类,包括登录,退出,拦截那些url等。

    MyAuthenticationProvinder类,主要实现认证

    
    import lombok.extern.log4j.Log4j;
    import lombok.extern.log4j.Log4j2;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    import java.util.Collection;
    
    @Log4j2
    @Component
    public class MyAuthenticationProvider implements AuthenticationProvider {
    
        @Autowired
        private MyUserDetailService myUserDetailService;
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    
            String userName = authentication.getName();// 这个获取表单输入中的用户名
            String password = (String) authentication.getCredentials();
            log.info("登陸用戶:"+userName);
            UserInfo userInfo = (UserInfo) myUserDetailService.loadUserByUsername(userName);
            
            String pwd = MD5Utils.encryptMD5Pwd(password,userInfo.getSalt());
            System.out.println(pwd);
            if(!pwd.equals(userInfo.getPassword())){
                throw new UsernameNotFoundException("用户名或者密码不正确");
            }
    
            Collection<? extends GrantedAuthority> authorities = userInfo.getAuthorities();
    
            return new UsernamePasswordAuthenticationToken(userInfo, pwd, authorities);
    
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return true;
        }
    }
    

    创建类MyUserDetailService实现UserDetailService

    
    import org.springframework.beans.factory.annotation.Autowired;
    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 java.util.Date;
    
    @Component
    public class MyUserDetailService implements UserDetailsService {
    
        @Autowired
        private UserRepo userRepo;
    
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
            //UserInfo userInfo = new UserInfo(1,"張三","abc","sdf",1);
            User user = userRepo.findFirstByAccount(s);
            if(user ==null){
                user = userRepo.findFirstByMobile(s);
                if(user == null){
                    throw new UsernameNotFoundException("用户名或者密码不正确");
                }
            }
            //保存最后一次登录日志
                    user.setLastLoginTime(new Date());
            userRepo.save(user);
            UserInfo userInfo = new UserInfo(
                    user.getId(),
                    user.getPassword(),
                    user.getSalt(),
                    user.getStatus(),
            return userInfo;
        }
    }
    

    创建类 MyAuthenticationSuccessHandler 继承 AuthenticationSuccessHandler 此类主要是SpringSecurity登录成功后的处理逻辑

    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    @Component
    public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
        @Override
        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
            httpServletResponse.sendRedirect("/index");
        }
    }
    

    创建类 MyAuthenticationFailHandler继承 AuthenticationFailHandler 此类主要是SpringSecurity登录失败后的处理逻辑

    
    import lombok.extern.log4j.Log4j2;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Log4j2
    @Component
    public class MyAuthenticationFailHandler implements AuthenticationFailureHandler {
    
        @Override
        public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
            log.info(e.getMessage());
            httpServletRequest.setAttribute("msg","");
            if(e instanceof UsernameNotFoundException){
                httpServletRequest.setAttribute("msg","用戶名或者密碼錯誤");
            }
            httpServletRequest.getRequestDispatcher("/login").forward(httpServletRequest,httpServletResponse);
    
        }
    }
    

    以上为主要配置,启动项目,访问/login会要求输入用户名密码。

  • 相关阅读:
    POJ 3071 概率DP
    BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
    POJ 1155 树形DP
    POJ 3252 组合数学?
    POJ 3641 快速幂
    POJ 3180 Tarjan
    POJ 3185 DFS
    POJ 3260 DP
    POJ 2392 DP
    99. Recover Binary Search Tree
  • 原文地址:https://www.cnblogs.com/c1024/p/11012055.html
Copyright © 2011-2022 走看看