spring boot使用spring security 的基本配置 以及 限制同一账号不能多处登录

关于如何spring boot 整合spring security 请自行百度,这里只是简单描述spring security 的配置项。 

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)// 启用 Spring Security 全局方法
//prePostEnabled :确定 Spring Security 前置注释 [@PreAuthorize,@PostAuthorize,..] 是否应该启用;
// secureEnabled : 确定 Spring Security 安全注释 [@Secured] 是否应该启用;
// jsr250Enabled : 确定 JSR-250注释 [@RolesAllowed..] 是否应该启用;
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImp userDetailsService;

    @Autowired
    private MysuccessHandle mysuccessHandle;

    // 该方法定义认证用户信息获取的来源、密码校验的规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    //auth.authenticationProvider(myauthenticationProvider)  自定义密码校验的规则

        //如果需要改变认证的用户信息来源,我们可以实现UserDetailsService
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());

        //inMemoryAuthentication 从内存中获取
        //	auth.inMemoryAuthentication().withUser("chengli").password("123456").roles("USER");

        //jdbcAuthentication从数据库中获取,但是默认是以security提供的表结构
        //usersByUsernameQuery 指定查询用户SQL
        //authoritiesByUsernameQuery 指定查询权限SQL
        //auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery(query).authoritiesByUsernameQuery(query);

        //注入userDetailsService,需要实现userDetailsService接口
        //auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin().loginPage("/login.html") //定义登录页面 或 转到登录页的url
                .loginProcessingUrl("/user/login")//自定义 表单提交登录的url  默认 /login
                .usernameParameter("userName")//自定义登录参数名 默认为 username
                .passwordParameter("passWord")//自定义登录参数名 默认为 password
                .defaultSuccessUrl("/success.html") //默认登录成功 url
              //  .successForwardUrl("/success") //登录成功的重定向 只能设置控制层url 不能设置为页面   如果同时设置了 defaultSuccessUrl successForwardUrl 后面的会覆盖前面的设置
               // .successHandler(mysuccessHandle) //登录成功的回调,可以自定义处理  如果同时设置了其他成功处理  最后的总会覆盖前面的设置
                .failureUrl("/error.html")  //登录失败系统转向的url ,默认是this.loginPage + "?error"。这里有个坑,这里默认是没有权限的! 我们必须给它额外配置一个适当的登录权限,或者设置不需要保护。否则是跳转不过去的,会跳转到登录页面
                .failureForwardUrl("/error1") //登录失败的重定向  failureUrl failureForwardUrl  同时设置时 后面的设置会覆盖前面的设置。
               // .failureHandler(myfailureHandler) //登录失败的回调 如果同时设置了其他的失败处理 最后设置的会覆盖前面的
                //defaultSuccessUrl successForwardUrl successHandler 基本只使用其中一个就可以了
                //failureUrl  failureForwardUrl  failureHandler
                .and()
                .authorizeRequests() //定义哪些url 是否需要保护
                .antMatchers("/login.html")  //ant 匹配路径参数格式
                .permitAll() // 路径 /login.htm  可以被任何人访问到
                .anyRequest() //其他任何请求
                .authenticated() //需要在登录验证后才可以访问
                .and()
                .headers().frameOptions().disable() //项目中用到iframe嵌入网页时 ,需要关闭
                .and()
                .csrf().disable();//关闭csrf 防护


        http.logout().logoutUrl("/mylogout") //指定登出的url
            .logoutSuccessUrl("/home")//登出转到的页面
            .permitAll();

        http.exceptionHandling().accessDeniedHandler((HttpServletRequest httpServletRequest, HttpServletResponse response, AccessDeniedException e)->{ //权限不足处理

                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                response.setCharacterEncoding("UTF-8");
                PrintWriter out = response.getWriter();
                out.write("{\"status\":\"error\",\"msg\":\"权限不足,请联系管理员!\"}");
                out.flush();
                out.close();

        })// 权限不足的回调
          .authenticationEntryPoint(myAuthenticationEntryPoint);// 未登录或者登陆过期、未授权 的拦截回调



        //设置同一账号仅一次登录 后面别处登录会剔除前面的登录。  
        //需要重写 实现了UserDetails的User的三个方法
//        @Override
//        public String toString() {
//            return this.userName;
//        }
//
//        @Override
//        public int hashCode() {
//            return this.userName.hashCode();
//        }
//
//        @Override
//        public boolean equals(Object obj) {
//            return this.toString().equals(obj.toString());
//        }
        http.sessionManagement()//Session管理器
                .maximumSessions(1) 
                .expiredUrl("/expiredPage");//被踢出时转到得页面  默认没有权限 所以需要配置不需要认证 不然访问不到






        //高级配置方式
//        .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
//             @Override
//             public <O extends FilterSecurityInterceptor> O postProcess(O o) {
//                        o.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);/根据一个url请求,获得访问它所需要的roles权限
//                        o.setAccessDecisionManager(myAccessDecisionManager);//接收一个用户的信息和访问一个url所需要的权限,判断该用户是否可以访问
//                        return o;
//             }

    }


    //在这里配置哪些url 不需要认证
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/error.html"); //参数为 ant 路径格式, 直接匹配url
//        mvcMatchers 同上,但是用于匹配 @RequestMapping 的value
//        regexMatchers 同上,但是为正则表达式

    }


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


}

failureHandler 和successHandler 

@Component
public class MyfailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        System.out.println(e.getMessage());
        httpServletResponse.getWriter().write("登录失败");
    }
}



@Component
public class MysuccessHandle implements AuthenticationSuccessHandler {


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

        //什么都不做的话,那就直接调用父类的方法
       // super.onAuthenticationSuccess(httpServletRequest, httpServletResponse, authentication);

        String url=httpServletRequest.getRequestURI();
        System.out.print("requestUrl:"+url);
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write("登录成功");
      //  new DefaultRedirectStrategy().sendRedirect(httpServletRequest, httpServletResponse, "/index");

    }
}

UserDetailsService

@Component
public class UserDetailsServiceImp implements UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        System.out.println("用户的用户名:"+ s);

        //根据用户名去数据库查询 最后返回 实现了UserDetails的user 对象

        return new User(s,passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

AuthenticationProvider

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsServiceImp serviceImp;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //username
        System.out.println("user name: " + authentication.getName());
        //password
        System.out.println("password: " + authentication.getCredentials());
        System.out.println("getPrincipal: " + authentication.getPrincipal());
        System.out.println("getAuthorities: " + authentication.getAuthorities());
        System.out.println("getDetails: " + authentication.getDetails());


        UserDetails userDetails = serviceImp.loadUserByUsername(authentication.getName());

        if(userDetails==null)throw new UsernameNotFoundException("该用户不存在");

        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
                userDetails, authentication.getCredentials(), userDetails.getAuthorities());
        return result;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

 

参考自:https://www.cnblogs.com/FlyAway2013/p/8037268.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值