zoukankan      html  css  js  c++  java
  • SpringSecurity-认证和授权

    表单登录

    单体应用

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
        //5.0以后默认使用非明文密码,如下方式使用已经过时的明文密码验证
        @Bean
        PasswordEncoder passwordEncoder(){
            return NoOpPasswordEncoder.getInstance();
        }
        
        
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //返回一个url拦截注册器,通过他来匹配需要拦截的请求
                    .anyRequest().authenticated() //所有请求都要被拦截进行认证
                    .and()//回到HttpSecurity http
                .ignoring().antMatchers("js/**","css/**")//静态自愿放行
                	.and()
                .formLogin() //返回一个SpringScurity提供的表单认证配置器
                    .loginPage("/myLogin.html") //指定自定义登录页,同时会以/myLogin.html注册一个Post路由,用于接收登录请求
                    .loginProcessingUrl("/login")//代替默认注册的验证路由,使用自定义路由接收登陆请求
                    .successForwardUrl("/index.html")//登录成功的跳转页面
                    .failureForwardUrl("/error.html")//登录失败的跳转页面
                    .usernameParameter("user")//替换默认接收用户名参数(username)为user
                    .passwordParameter("pwd")//替换默认接收密码参数(password)为pwd
                    .permitAll()//对操作路由进行放行
                    .and()
                .csrf().disable();//跨站请求伪造防护功能,当继承WebSecurityConfigurerAdapter时会默认开启csrf()方法
        }
    }
    

    前后端分离应用

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //返回一个url拦截注册器,通过他来匹配需要拦截的请求
                    .anyRequest().authenticated() //所有请求都要被拦截进行认证
                    .and()//回到HttpSecurity http
                .formLogin() //返回一个SpringScurity提供的表单认证配置器
                    .loginPage("/myLogin.html") //指定自定义登录页,同时会以/myLogin.html注册一个Post路由,用于接收登录请求
                    .loginProcessingUrl("/login")//代替默认注册的验证路由,使用自定义路由接收登陆请求
                    .successForwardUrl("/index.html")//登录成功的跳转页面
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            PrintWriter out = httpServletResponse.getWriter();
                            out.write("{"error_code":"0","message":"登录成功"}");
                        }
                    })//登录成功返回json数据
                    .failureHandler(new AuthenticationFailureHandler() {
                        @Override
                        public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            PrintWriter out = httpServletResponse.getWriter();
                            out.write("{"error_code":"401","message":"登录验证失败"}");
                        }
                    })//登录失败返回json数据
                    .usernameParameter("user")//替换默认接收用户名参数(username)为user
                    .passwordParameter("pwd")//替换默认接收密码参数(password)为pwd
                    .permitAll()//对操作路由进行放行
                    .and()
                .csrf().disable();//跨站请求伪造防护功能,当继承WebSecurityConfigurerAdapter时会默认开启csrf()方法
        }
    }
    
    

    授权

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //返回一个url拦截注册器,通过他来匹配需要拦截的请求
                    .anyRequest().authenticated() //所有请求都要被拦截进行认证
                    .antMatchers("/admin/api/**").hasAnyRole("ADMIN")//admin角色用户可以访问限制
                    .antMatchers("/user/api/**").hasAnyRole("USER")//user角色用户访问限制
                    .antMatchers("/app/api/**").permitAll()//所有角色用户都可访问
                    .and()//回到HttpSecurity http
                .formLogin() //返回一个SpringScurity提供的表单认证配置器
                    .loginPage("/myLogin.html") //指定自定义登录页,同时会以/myLogin.html注册一个Post路由,用于接收登录请求
                    .loginProcessingUrl("/login")//代替默认注册的验证路由,使用自定义路由接收登陆请求
                    .successForwardUrl("/index.html")//登录成功的跳转页面
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            PrintWriter out = httpServletResponse.getWriter();
                            out.write("{"error_code":"0","message":"登录成功"}");
                        }
                    })//登录成功返回json数据
                    .failureHandler(new AuthenticationFailureHandler() {
                        @Override
                        public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            PrintWriter out = httpServletResponse.getWriter();
                            out.write("{"error_code":"401","message":"登录验证失败"}");
                        }
                    })//登录失败返回json数据
                    .usernameParameter("user")//替换默认接收用户名参数(username)为user
                    .passwordParameter("pwd")//替换默认接收密码参数(password)为pwd
                    .permitAll()//对操作路由进行放行
                    .and()
                .csrf().disable();//跨站请求伪造防护功能,当继承WebSecurityConfigurerAdapter时会默认开启csrf()方法
        }
    }
    

    antMatchers()是一个采用ANT模式的URL匹配器。

    • 匹配任意单个字符 *
    • 匹配任意多个字符 **

    认证和授权

    基于内存的多用户支持

    实现自定义的UserDetailsService,任何实现UserDetailsService接口的对象都可以作为验证数据源

    InMemoryUserDetailsManager是UserDetailsService接口中的一个实现类,它将用户数据源寄存在内存里,这里仅仅调用createUser()生成两个用户,并赋予相应的角色。

        @Bean
        public UserDetailsService userDetailsService(){
            InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
            inMemoryUserDetailsManager.createUser(User.withUsername("liuhui").password("12121").roles("ADMIN").build());
            inMemoryUserDetailsManager.createUser(User.withUsername("zhujie").password("12121").roles("USER").build());
            return inMemoryUserDetailsManager;
        }
    

    基于默认数据库模型的多用户支持

    JdbcUserDetailsManager帮助我们以JDBC的方式对接数据库和Spring Security,它设定了一个默认的数据库模型。

    JdbcUserDetailsManager需要两个表,User表和authorities表,用来描述角色和权限的关联

    Users:用户名、密码、是否可用

    authorities:用户名、权限

    相对于基于内存的方式很相似,主要区别是相当于把用户信息保存到了数据库中,比如creatUser相当于在数据库中执行

    insert into users(username,password,enabled) values(?,?,?)
    

        @Autowired
        private DataSource dataSource;
    
        @Bean
        public UserDetailsService userDetailsService(){
            JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
            jdbcUserDetailsManager.setDataSource(dataSource);
    
            jdbcUserDetailsManager.createUser(User.withUsername("liuhui").password("12121").roles("ADMIN").build());
            jdbcUserDetailsManager.createUser(User.withUsername("zhujie").password("12121").roles("USER").build());
            return jdbcUserDetailsManager;
        }
    

    基于自定义数据库模型的认证和授权

    编写一个用户实体实现UserDetails

    public class User implements UserDetails {
    
        private Long id;//用户id
        private String username;//用户名
        private String password;//密码
        private String roles;//权限信息
        private boolean enbled;//是否启用
        private List<GrantedAuthority> authorities;
    
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return null;
        }
    
        @Override
        public String getPassword() {
            return null;
        }
    
        @Override
        public String getUsername() {
            return null;
        }
    
        @Override
        public boolean isAccountNonExpired() { //是否过期
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() { //是否锁定
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() { //用户凭证是否过期
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return enbled;
        }
        //set//get
    

    编写通过用户名查找用户的mapper

    public interface UserMapper {
        @Select("SELECT * FROM users WHERE username=#{username}")
        User findByUserName(@Param("username") String username);
    }
    
    

    编写MyUserDetailsService并实现UserDetailsService

    @Service
    public class MyUserDetailService implements UserDetailsService {
        @Autowired
        UserMapper userMapper;
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //从数据库尝试读取该用户
            User user = userMapper.findByUserName(username);
            //用户不存在,抛出异常
            if(user == null){
                throw new UsernameNotFoundException("用户不存在!");
            }
            //将数据库形式的roles解析为UserDetails的权限集
            //AuthorityUtils.commaSeparatedStringToAuthorityList是SpringSecurity提供的,该方法用于将逗号隔开的权限集字符串切割成可用权限集合
            //也可自己实现
            user.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));
            return user;
        }
    }
    
    
  • 相关阅读:
    四川第七届 C Censor (字符串哈希)
    四川第七届 C Censor (字符串哈希)
    Android:实现两个Activity相互切换而都不走onCreate()
    正宗佛祖凝视-原装正版
    iOS中数组遍历的方法及比較
    html5 返回当前地理位置的坐标点(经纬度)
    Android之——卸载应用程序
    Android—— 4.2 Vold挂载管理_NetlinkManager (四)
    2014年java软件project师面试题收集
    C++刷题——2736: 指针练习--输出最大值
  • 原文地址:https://www.cnblogs.com/luckyhui28/p/13550576.html
Copyright © 2011-2022 走看看