zoukankan      html  css  js  c++  java
  • JavaWeb-SpringSecurity在数据库中查询登陆用户

      系列博文

      项目已上传至guthub  传送门

      JavaWeb-SpringSecurity初认识  传送门

      JavaWeb-SpringSecurity在数据库中查询登陆用户  传送门

      JavaWeb-SpringSecurity自定义登陆页面  传送门

      JavaWeb-SpringSecurity实现需求-判断请求是否以html结尾  传送门

      JavaWeb-SpringSecurity自定义登陆配置  传送门

      JavaWeb-SpringSecurity图片验证ImageCode  传送门

      JavaWeb-SpringSecurity记住我功能  传送门

      JavaWeb-SpringSecurity使用短信验证码登陆  传送门

      在MySQL数据库中创建springsecurity数据库

      

       (id、username、password都是根据User.java映射过来的)

      在application.properties中编写配置文件

    #datasource
    spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.dricer-class-name=com.mysql.jdbc.Driver
    
    #jpa
    #打印出数据库语句
    spring.jpa.show-sql=true
    #更新数据库表
    spring.jpa.hibernate.ddl-auto=update

      创建domain实体层User.java和repository存储层接口UserRepository.java  

      书写用户User.java实体

        //用户是否没有失效
        @Transient
        private boolean accountNonExpried;
        //用户是否冻结
        @Transient
        private boolean accountNonLocked;
        //证明是否过期
        @Transient
        private boolean credentialsNonExpired;
        //判断是否删除
        @Transient
        private boolean enabled;
        @Transient
        //添加    @Transient 注解可以不将  Set<GrantedAuthority>映射到数据库表上
        private Set<GrantedAuthority> authorities;
    
    
    //给hibernatre用的构造方法
        protected User() {
            
        }
        
        public User(Long id,String username,String password)
        {
            this.id = id;
            this.username = username;
            this.password = password;
        }
        
        //给SpringSecurity用的构造方法
        public User(String username,String password,
                Collection<? extends GrantedAuthority> authorities) {
                this(username,password,true,true,true,true,authorities);
        }
        
        public User(String username, String password, boolean enabled,
                boolean accountNonExpired, boolean credentialsNonExpired,
                boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
    
            if (((username == null) || "".equals(username)) || (password == null)) {
                throw new IllegalArgumentException(
                        "Cannot pass null or empty values to constructor");
            }
    
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpried = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        }
        
        private static SortedSet<GrantedAuthority> sortAuthorities(
                Collection<? extends GrantedAuthority> authorities) {
            Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
            // Ensure array iteration order is predictable (as per
            // UserDetails.getAuthorities() contract and SEC-717)
            SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
                    new AuthorityComparator());
    
            for (GrantedAuthority grantedAuthority : authorities) {
                Assert.notNull(grantedAuthority,
                        "GrantedAuthority list cannot contain any null elements");
                sortedAuthorities.add(grantedAuthority);
            }
    
            return sortedAuthorities;
        }
        
        private static class AuthorityComparator implements Comparator<GrantedAuthority>,
        Serializable {
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
        // Neither should ever be null as each entry is checked before adding it to
        // the set.
        // If the authority is null, it is a custom authority and should precede
        // others.
        if (g2.getAuthority() == null) {
            return -1;
        }
    
        if (g1.getAuthority() == null) {
            return 1;
        }
    
        return g1.getAuthority().compareTo(g2.getAuthority());
        }
        }
    package com.Gary.GaryRESTful.domain;
    
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Set;
    import java.util.SortedSet;
    import java.util.TreeSet;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Transient;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.SpringSecurityCoreVersion;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.util.Assert;
    
    @Entity
    public class User implements UserDetails{
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String username;
        private String password;
        
        //用户是否没有失效
        @Transient
        private boolean accountNonExpried;
        //用户是否冻结
        @Transient
        private boolean accountNonLocked;
        //证明是否过期
        @Transient
        private boolean credentialsNonExpired;
        //判断是否删除
        @Transient
        private boolean enabled;
        @Transient
        //添加    @Transient 注解可以不将  Set<GrantedAuthority>映射到数据库表上
        private Set<GrantedAuthority> authorities;
        
        //给hibernatre用的构造方法
        protected User() {
            
        }
        
        public User(Long id,String username,String password)
        {
            this.id = id;
            this.username = username;
            this.password = password;
        }
        
        //给SpringSecurity用的构造方法
        public User(String username,String password,
                Collection<? extends GrantedAuthority> authorities) {
                this(username,password,true,true,true,true,authorities);
        }
        
        public User(String username, String password, boolean enabled,
                boolean accountNonExpired, boolean credentialsNonExpired,
                boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
    
            if (((username == null) || "".equals(username)) || (password == null)) {
                throw new IllegalArgumentException(
                        "Cannot pass null or empty values to constructor");
            }
    
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpried = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        }
        
        private static SortedSet<GrantedAuthority> sortAuthorities(
                Collection<? extends GrantedAuthority> authorities) {
            Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
            // Ensure array iteration order is predictable (as per
            // UserDetails.getAuthorities() contract and SEC-717)
            SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
                    new AuthorityComparator());
    
            for (GrantedAuthority grantedAuthority : authorities) {
                Assert.notNull(grantedAuthority,
                        "GrantedAuthority list cannot contain any null elements");
                sortedAuthorities.add(grantedAuthority);
            }
    
            return sortedAuthorities;
        }
        
        private static class AuthorityComparator implements Comparator<GrantedAuthority>,
        Serializable {
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
        // Neither should ever be null as each entry is checked before adding it to
        // the set.
        // If the authority is null, it is a custom authority and should precede
        // others.
        if (g2.getAuthority() == null) {
            return -1;
        }
    
        if (g1.getAuthority() == null) {
            return 1;
        }
    
        return g1.getAuthority().compareTo(g2.getAuthority());
        }
        }
        
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
        //用户权限
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            // TODO Auto-generated method stub
            return authorities;
        }
        
        //用户是否没有失效
        @Override
        public boolean isAccountNonExpired() {
            // TODO Auto-generated method stub
            return accountNonExpried;
        }
        
        //用户是否被冻结
        @Override
        public boolean isAccountNonLocked() {
            // TODO Auto-generated method stub
            return accountNonLocked;
        }
        
        //用户是否证明权限过期
        @Override
        public boolean isCredentialsNonExpired() {
            // TODO Auto-generated method stub
            return credentialsNonExpired;
        }
        
        //判断用户是否删除
        @Override
        public boolean isEnabled() {
            // TODO Auto-generated method stub
            return enabled;
        }
        
        
        
    }
    User.java

      完善User.java实体

        public User(Long id,String username,String password)
        {
            this.id = id;
            this.username = username;
            this.password = password;
        }
        
        //给SpringSecurity用的构造方法
        public User(String username,String password,
                Collection<? extends GrantedAuthority> authorities) {
                this(username,password,true,true,true,true,authorities);
        }
        
        public User(String username, String password, boolean enabled,
                boolean accountNonExpired, boolean credentialsNonExpired,
                boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
    
            if (((username == null) || "".equals(username)) || (password == null)) {
                throw new IllegalArgumentException(
                        "Cannot pass null or empty values to constructor");
            }
    
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpried = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        }
        
        private static SortedSet<GrantedAuthority> sortAuthorities(
                Collection<? extends GrantedAuthority> authorities) {
            Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
            // Ensure array iteration order is predictable (as per
            // UserDetails.getAuthorities() contract and SEC-717)
            SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
                    new AuthorityComparator());
    
            for (GrantedAuthority grantedAuthority : authorities) {
                Assert.notNull(grantedAuthority,
                        "GrantedAuthority list cannot contain any null elements");
                sortedAuthorities.add(grantedAuthority);
            }
    
            return sortedAuthorities;
        }
        
        private static class AuthorityComparator implements Comparator<GrantedAuthority>,
        Serializable {
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
        // Neither should ever be null as each entry is checked before adding it to
        // the set.
        // If the authority is null, it is a custom authority and should precede
        // others.
        if (g2.getAuthority() == null) {
            return -1;
        }
    
        if (g1.getAuthority() == null) {
            return 1;
        }
    
        return g1.getAuthority().compareTo(g2.getAuthority());
        }
        }
    package com.Gary.GaryRESTful.domain;
    
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Set;
    import java.util.SortedSet;
    import java.util.TreeSet;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.SpringSecurityCoreVersion;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.util.Assert;
    
    @Entity
    public class User implements UserDetails{
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String username;
        private String password;
        
        //用户是否没有失效
        private boolean accountNonExpried;
        //用户是否冻结
        private boolean accountNonLocked;
        //证明是否过期
        private boolean credentialsNonExpired;
        //判断是否删除
        private boolean enabled;
        private Set<GrantedAuthority> authorities;
        
        //给hibernatre用的构造方法
        protected User() {
            
        }
        
        public User(Long id,String username,String password)
        {
            this.id = id;
            this.username = username;
            this.password = password;
        }
        
        //给SpringSecurity用的构造方法
        public User(String username,String password,
                Collection<? extends GrantedAuthority> authorities) {
                this(username,password,true,true,true,true,authorities);
        }
        
        public User(String username, String password, boolean enabled,
                boolean accountNonExpired, boolean credentialsNonExpired,
                boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
    
            if (((username == null) || "".equals(username)) || (password == null)) {
                throw new IllegalArgumentException(
                        "Cannot pass null or empty values to constructor");
            }
    
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpried = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        }
        
        private static SortedSet<GrantedAuthority> sortAuthorities(
                Collection<? extends GrantedAuthority> authorities) {
            Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
            // Ensure array iteration order is predictable (as per
            // UserDetails.getAuthorities() contract and SEC-717)
            SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(
                    new AuthorityComparator());
    
            for (GrantedAuthority grantedAuthority : authorities) {
                Assert.notNull(grantedAuthority,
                        "GrantedAuthority list cannot contain any null elements");
                sortedAuthorities.add(grantedAuthority);
            }
    
            return sortedAuthorities;
        }
        
        private static class AuthorityComparator implements Comparator<GrantedAuthority>,
        Serializable {
        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
        // Neither should ever be null as each entry is checked before adding it to
        // the set.
        // If the authority is null, it is a custom authority and should precede
        // others.
        if (g2.getAuthority() == null) {
            return -1;
        }
    
        if (g1.getAuthority() == null) {
            return 1;
        }
    
        return g1.getAuthority().compareTo(g2.getAuthority());
        }
        }
        
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
        //用户权限
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            // TODO Auto-generated method stub
            return authorities;
        }
        
        //用户是否没有失效
        @Override
        public boolean isAccountNonExpired() {
            // TODO Auto-generated method stub
            return accountNonExpried;
        }
        
        //用户是否被冻结
        @Override
        public boolean isAccountNonLocked() {
            // TODO Auto-generated method stub
            return accountNonLocked;
        }
        
        //用户是否证明权限过期
        @Override
        public boolean isCredentialsNonExpired() {
            // TODO Auto-generated method stub
            return credentialsNonExpired;
        }
        
        //判断用户是否删除
        @Override
        public boolean isEnabled() {
            // TODO Auto-generated method stub
            return enabled;
        }
        
        
        
    }
    User.java

      完善UserRepository.java接口,实现查找用户姓名方法

        @Query(value = "select * from user where username = ?1",nativeQuery = true)
        User findUserByUsername(String username);

      在UserService.java中实现查找用户Service

        @Autowired
        private PasswordEncoder passwordEncoder;
        
        @Autowired
        private UserRepository userRepository;
        
        //spring security默认处理登陆(username为输入的username)
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // TODO Auto-generated method stub
            //System.out.println(username);
            User user = userRepository.findUserByUsername(username);
            //用户名,密码,权限
            //User实现UserDetails接口
            return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }

      测试时发现,当用户输入错误的用户名和密码时,控制台会报空指针异常,前台为给出“坏的凭证”给用户提示信息。

      原因:springsecurity会拦截一切其它的请求。只有当用户输入正确的用户名和密码,springsecurity才会释放用户正常的请求。

    package com.Gary.GaryRESTful.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    
    //Web应用安全适配器
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
    
        //告诉SpringSecurity密码用什么加密的
        @Bean
        public PasswordEncoder passwordEncoder()
        {
            return new BCryptPasswordEncoder();
        }
        
        
        //表单验证(身份认证)
        protected void configure(HttpSecurity http) throws Exception{
            http.formLogin()
                .and()
                //请求授权
                .authorizeRequests()
                //所有请求都被拦截,跳转到(/login请求中)
                .anyRequest()
                //都需要我们身份认证
                .authenticated();
        }
        
    }
    SecurityConfig.java
    package com.Gary.GaryRESTful.repository;
    
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.data.repository.CrudRepository;
    
    import com.Gary.GaryRESTful.domain.User;
    
    public interface UserRepository extends CrudRepository<User,Long>{
    
        @Query(value = "select * from user where username = ?1",nativeQuery = true)
        User findUserByUsername(String username);
        
    }
    UserRepository.java
    package com.Gary.GaryRESTful.service;
    
    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.Component;
    
    import com.Gary.GaryRESTful.domain.User;
    import com.Gary.GaryRESTful.repository.UserRepository;
    
    
    //用SprinSecurity默认的登陆系统
    //UserService要实现UserDetailsService接口
    @Component
    public class UserService implements UserDetailsService{
    
        @Autowired
        private PasswordEncoder passwordEncoder;
        
        @Autowired
        private UserRepository userRepository;
        
        //spring security默认处理登陆(username为输入的username)
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // TODO Auto-generated method stub
            //System.out.println(username);
            User user = userRepository.findUserByUsername(username);
            //用户名,密码,权限
            //User实现UserDetails接口
            return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }
    
        
        
    }
    UserService.java

      所以我们可以在UserDetails.java中进行修改,添加判断,如果在数据库中未查询到用户时返回null

      @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // TODO Auto-generated method stub
            //System.out.println(username);
            User user = userRepository.findUserByUsername(username);
            //用户名,密码,权限
            if(user == null)
            {
                throw new UsernameNotFoundException(username);
            }
            //User实现UserDetails接口
            return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }

    package com.Gary.GaryRESTful.service;
    
    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.Component;
    
    import com.Gary.GaryRESTful.domain.User;
    import com.Gary.GaryRESTful.repository.UserRepository;
    
    
    //用SprinSecurity默认的登陆系统
    //UserService要实现UserDetailsService接口
    @Component
    public class UserService implements UserDetailsService{
    
        @Autowired
        private PasswordEncoder passwordEncoder;
        
        @Autowired
        private UserRepository userRepository;
        
        //spring security默认处理登陆(username为输入的username)
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // TODO Auto-generated method stub
            //System.out.println(username);
            User user = userRepository.findUserByUsername(username);
            //用户名,密码,权限
            if(user == null)
            {
                throw new UsernameNotFoundException(username);
            }
            //User实现UserDetails接口
            return new User(username,passwordEncoder.encode(user.getPassword()),AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }
    
        
        
    }
    UserService.java

      拓展:根据SpringSecurity提供的User方法

        //给SpringSecurity用的构造方法
        public User(String username,String password,
                Collection<? extends GrantedAuthority> authorities) {
                this(username,password,true,true,true,true,authorities);
        }

      可以在UserService.java中提供的UserDetails返回值中添加4个boolean值

    return new User(user.getUsername(),passwordEncoder.encode(user.getPassword()),true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));

      这四个boolean值代表着

            //用户是否没有失效
        @Transient
        private boolean accountNonExpried;
        //用户是否冻结
        @Transient
        private boolean accountNonLocked;
        //证明是否过期
        @Transient
        private boolean credentialsNonExpired;
        //判断是否删除
        @Transient
        private boolean enabled;    

      如果return返回值中四个参数都为true,springscurity不会去进行拦截验证,

      当其中一个参数为false时,springsecurity就会对用户进行拦截验证~

      

  • 相关阅读:
    sql server紧急状态下登录脚本
    将SQL for xml path('')中转义的字符正常显示
    SQL查询表中的有那些索引
    Set ARITHABORT Option设置为ON
    检测重编译
    计划指南
    sql server 清理缓存
    变量绑定
    分析及动态采样
    Hint
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/11745700.html
Copyright © 2011-2022 走看看