spring-security 起步

pom.xml


      org.springframework
      spring-webmvc
      5.1.2.RELEASE
    

    
      org.springframework.security
      spring-security-web
      5.1.2.RELEASE
    
    
      org.springframework.security
      spring-security-config
      5.1.2.RELEASE
    

加入过滤器

  1. 选择一:web.xml
  
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
  
  
    springSecurityFilterChain
    /*
  
  1. 选择二:AbstractSecurityWebApplicationInitializer
package cn.johnyu;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {

}

配置安全策略

  1. 使用配置文件,加入security的名称空间(暂时不可用)



    


  1. 使用配置类(继承WebSecurityConfigurerAdapter
package cn.johnyu.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     *用来修改过滤器链
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/images/**");
        web.ignoring().antMatchers("/js/**");
    }

    /**
     *配置UserDetailService,完成"鉴权"
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .passwordEncoder(new StandardPasswordEncoder("53cr3t"));
    }
    /**
     * 修改拦截器,保护请求
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                .antMatchers("/work")
                .hasAuthority("ROLE_READER")
                .antMatchers("/other")
                .hasAnyRole("GUEST","READER")
                .anyRequest().permitAll()
                .and()
                .formLogin()

                .and()
                .exceptionHandling()
                .accessDeniedPage("/forbidden")
                .and()
                .logout()
                .logoutUrl("/logout");
    }
}

关于登录页

  1. 如果没有Override configure(HttpSecurity),则会提供一个默认的登录页(否则没有)
  2. 如果加入.formLogin(),则会找回该登录页
  3. 该页核心内容如下:
  1. 你可以加入自定义的登录页,方法如下:
.formLogin()
                .loginPage("/login")
                .failureUrl("/login?error=true");

此时,如果有以下控制器

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

则会将页面转向到自定义的页面上。

关于退出

.and()
                .logout()
                .logoutUrl("/logout");

这将指定“/logout”为退出链接,退出后将回到“/login?logout”

关于role不符合

  1. 默认将返回403码
  2. 指定403页面的方法
.and()
                .exceptionHandling()
                .accessDeniedPage("/forbidden")

关于鉴权

  1. 可以使用void configure(AuthenticationManagerBuilder)进行
  2. 可以使用三种方法进行:
@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication();
        auth.inMemoryAuthentication();
        auth.ldapAuthentication();
    }
  1. 无论哪种方式,都将采用hash方式处理密码

使用JDBC进行鉴权

  1. 直接使用(无定制方式)
private DataSource dataSource;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
        .passwordEncoder(new StandardPasswordEncoder("53cr3t"));//这个是必选项
    }
  1. Security默认使用以下表的结构:schema.sql
-- ----------------------------
-- 用户表: username做为唯一字段
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
                         `id` int(8) NOT NULL AUTO_INCREMENT,
                         `username` varchar(20) DEFAULT NULL,
                         `password` varchar(100) DEFAULT NULL,
                         `enabled` tinyint(4) DEFAULT NULL,
                         PRIMARY KEY (`id`)
);

-- ----------------------------
-- 角色表:username外键关联users
-- 注意:它与用户表,存在着间接的 Many To Many 的关系,用户的角色可以来自:直接角色和所属组的角色
-- ----------------------------
DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities` (
                               `id` int(11) NOT NULL AUTO_INCREMENT,
                               `username` varchar(20) DEFAULT NULL,
                               `authority` varchar(50) DEFAULT NULL,
                               PRIMARY KEY (`id`)
);

-- ----------------------------
-- 用户组:
-- 注意:它与users存在 Many to Many的关系,但与authorities,是Many To One 的关系
-- ----------------------------
DROP TABLE IF EXISTS `groups`;
CREATE TABLE `groups` (
                          `id` int(11) NOT NULL AUTO_INCREMENT,
                          `groupname` varchar(50) DEFAULT NULL,
                          PRIMARY KEY (`id`)
);

-- ----------------------------
-- users 与 authorites 的一对一的关联表,group_Id外键关联groups表
-- ----------------------------
DROP TABLE IF EXISTS `group_authorities`;
CREATE TABLE `group_authorities` (
                                     `group_Id` int(11) NOT NULL AUTO_INCREMENT,
                                     `authority` varchar(50) DEFAULT NULL,
                                     PRIMARY KEY (`group_Id`)
);

-- ----------------------------
-- 用户 与 用户组 之间的多到多关联关系(username外键关联users表,group_Id外键关联groups表)
-- ----------------------------
DROP TABLE IF EXISTS `group_members`;
CREATE TABLE `group_members` (
                                 `id` int(11) NOT NULL AUTO_INCREMENT,
                                 `username` varchar(20) DEFAULT NULL,
                                 `group_Id` int(11) DEFAULT NULL,
                                 PRIMARY KEY (`id`)
);

初如化的数据:data.sql

-- 密码为123(salt=53cr3t new StandardPasswordEncoder("53cr3t").encode("123"))
insert  into users (username,password,enabled) values('john','97c1e5a28f4d983316d375550e1e28ee50b6d27b5c5a71d6daa4c694227a8d8d94e8e6917ca4ad13',1);
insert  into users (username,password,enabled) values('tom','123',0);
insert  into users (username,password,enabled) values('alice','221a34d7021d75c196b80cbeb0ce53818871ab2a27be7113afc1ee1d08ab157c19cdef4490a06080',1);
-- 必须确保User具有Role
insert into authorities (username,authority) values('john','ROLE_READER');
insert into authorities (username,authority) values('tom','ROLE_READER');
insert into authorities (username,authority) values('alice','ROLE_GUEST');

附:三条核心查询语句:

public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, MessageSourceAware {
//用于用户身份认证
    public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enabled from users where username = ?";
//查询用户的角色
    public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority from authorities where username = ?";
//查询用户所属的组的角色
    public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY = "select g.id, g.group_name, ga.authority from groups g, group_members gm, group_authorities ga where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id";

你可能感兴趣的:(spring-security 起步)