spring boot + spring security 基于 前端 ajax Content-Type为applications-json的 post方式的登陆 以及权限认证

1,maven依赖 加入

    
        org.springframework.boot
        spring-boot-starter-security
    

**

2,自定义WebSecurityConfigurerAdapter 的实现类

**

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
@Autowired
private UserService userService;


@Autowired
private AuthenticationAccessDeniedHandler accessDeniedHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
     http.formLogin()  
      .loginPage("/user/usercontroller/login_page")
      .loginProcessingUrl("/user/usercontroller/login").permitAll()
      .and()
      .authorizeRequests()    // 定义哪些URL需要被保护、哪些不需要被保护
      .antMatchers("/user/usercontroller/login_page").permitAll()   // 设置所有人都可以访问的路径
      .anyRequest()        // 任何请求,登录后可以访问
      .authenticated()
      .and()
      .csrf().disable();     // 关闭csrf防护
      http.addFilterBefore(myFilterSecurityInterceptor,FilterSecurityInterceptor.class);
        //用重写的Filter替换掉原有的UsernamePasswordAuthenticationFilter
      http.addFilterAt(customAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
      http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);

}

//注册自定义的UsernamePasswordAuthenticationFilter
@Bean
CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
    CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
    filter.setAuthenticationSuccessHandler(new SuccessHandler());
    filter.setAuthenticationFailureHandler(new FailureHandler());
    filter.setFilterProcessesUrl("/user/usercontroller/login");
    //这句很关键,重用WebSecurityConfigurerAdapter配置的AuthenticationManager,不然要自己组装AuthenticationManager
    filter.setAuthenticationManager(authenticationManagerBean());
    return filter;
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
   auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() { 
       @Override
       public String encode(CharSequence rawPassword) {
           return Md5Utils.encryptPassword((String) rawPassword, (String) rawPassword);
       }

       @Override
       public boolean matches(CharSequence rawPassword, String encodedPassword) {
           return encodedPassword.equals(Md5Utils.encryptPassword((String) rawPassword,(String) rawPassword));
       }
   });

}

}

3,继承 UserDetailsService 并实现认证方法

 @Service
 public class UserServiceImpl implements UserService,UserDetailsService {

@Autowired
UserMapper userDao;

@Autowired
PermissionMapper permissionDao;

@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
        User user = userDao.loadUserByUsername(username);
        if (user != null) {
            List permissions = permissionDao.getAllowsPermissions(user.getId());
            List grantedAuthorities = new ArrayList <>();
            for (Permission permission : permissions) {
                if (permission != null && permission.getCode()!=null) {

                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getCode());
                //1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
                grantedAuthorities.add(grantedAuthority);
                }
            }
            user.setPermission(grantedAuthorities);
            return user;
        } else {
            throw new ServiceException("admin: " + username + " do not exist!");
        }
}

}

4,编写 实现 security 中的 UserDetails 的 自定义 user类

    /**
     * 
     * 用户
     * 
     * @author liuwei
     *
     */
            public class User  implements Serializable,UserDetails {

private static final long serialVersionUID = 6981667711419946989L;

// '主键' id
private Integer id;

// '用户名'
private String userName;

// '密码'
private String passWord;

// '中文名'
private String chineseName;

// '账号状态 0:正常使用 1:禁用'
private Integer statu;

// '角色类型',
private Integer roleId;

// '办公电话'
private String phoneNumber;

// '手机号'
private String mobilePhone;

// '所属组织机构',
private Integer company;

// '邮箱'
private String email;

// '更新时间',
private Date updateTime;

// '更新人'
private String updateUser;

// '创建时间',
private Timestamp createTime;

// '创建人id',
private String createrPerson;


private Collection permission;

public void setPermission(Collection permission) {
    this.permission = permission;
}

public Integer getId() {
    return id;
}

public void setId(Integer 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;
}

public String getChineseName() {
    return chineseName;
}

public void setChineseName(String chineseName) {
    this.chineseName = chineseName;
}




public Integer getStatu() {
    return statu;
}

public void setStatu(Integer statu) {
    this.statu = statu;
}

public Integer getRoleId() {
    return roleId;
}

public void setRoleId(Integer roleId) {
    this.roleId = roleId;
}

public String getPhoneNumber() {
    return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
}

public String getMobilePhone() {
    return mobilePhone;
}

public void setMobilePhone(String mobilePhone) {
    this.mobilePhone = mobilePhone;
}

public Integer getCompany() {
    return company;
}

public void setCompany(Integer company) {
    this.company = company;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public Date getUpdateTime() {
    return updateTime;
}

public void setUpdateTime(Date updateTime) {
    this.updateTime = updateTime;
}

public String getUpdateUser() {
    return updateUser;
}

public void setUpdateUser(String updateUser) {
    this.updateUser = updateUser;
}

public Timestamp getCreateTime() {
    return createTime;
}

public void setCreateTime(Timestamp createTime) {
    this.createTime = createTime;
}

public String getCreaterPerson() {
    return createrPerson;
}

public void setCreaterPerson(String createrPerson) {
    this.createrPerson = createrPerson;
}



@Override
public Collection getAuthorities() {
    return permission;
}

@Override
public String getPassword() {
    return this.passWord;
}

@Override
public String getUsername() {
    return this.userName;
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}

}

5,自定义 json 的解析 类

/**
 * AuthenticationFilter that supports rest login(json login) and form login.
 * @author 刘维
 */
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

@SuppressWarnings("finally")
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    String param= null; 
    //Content-Type is json 自己去实现 json解析
    if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
            ||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
        UsernamePasswordAuthenticationToken authRequest=null;
        try (InputStream is = request.getInputStream()){
            BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null)
                responseStrBuilder.append(inputStr);

            JSONObject jsonObject = JSONObject.parseObject(responseStrBuilder.toString());
            param= jsonObject.toJSONString();
            AuthenticationBean bean=(AuthenticationBean) JSONUtils.jsonToBean(param, new AuthenticationBean());
            authRequest=new UsernamePasswordAuthenticationToken(bean.getUserName(),bean.getPassword());
        }catch (IOException e) {
            e.printStackTrace();
            authRequest = new UsernamePasswordAuthenticationToken("", "");
        }finally {
            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

    //transmit it to UsernamePasswordAuthenticationFilter
    else {
        return super.attemptAuthentication(request, response);
    }
}

}

6,加入 jsonutils 的 工具类

public class JSONUtils {
    /**
     * Bean对象转JSON
     * 
     * @param object
     * @param dataFormatString
     * @return
     */
    public static String beanToJson(Object object, String dataFormatString) {
        if (object != null) {
            if (StringUtils.isEmpty(dataFormatString)) {
                return JSONObject.toJSONString(object);
            }
            return JSON.toJSONStringWithDateFormat(object, dataFormatString);
        } else {
            return null;
        }
    }

/**
 * Bean对象转JSON
 * 
 * @param object
 * @return
 */
public static String beanToJson(Object object) {
    if (object != null) {
        return JSON.toJSONString(object);
    } else {
        return null;
    }
}

/**
 * String转JSON字符串
 * 
 * @param key
 * @param value
 * @return
 */
public static String stringToJsonByFastjson(String key, String value) {
    if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
        return null;
    }
    Map map = new HashMap();
    map.put(key, value);
    return beanToJson(map, null);
}

/**
 * 将json字符串转换成对象
 * 
 * @param json
 * @param clazz
 * @return
 */
public static Object jsonToBean(String json, Object clazz) {
    if (StringUtils.isEmpty(json) || clazz == null) {
        return null;
    }
    return JSON.parseObject(json, clazz.getClass());
}


/**
 * json字符串转map
 * 
 * @param json
 * @return
 */
@SuppressWarnings("unchecked")
public static Map jsonToMap(String json) {
    if (StringUtils.isEmpty(json)) {
        return null;
    }
    return JSON.parseObject(json, Map.class);
}

}

8,定义权限越权操作的处理类

/**
 * Created by 刘维
 */
@Component
public class AuthenticationAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse resp, AccessDeniedException e) throws IOException, ServletException {
        resp.setStatus(HttpServletResponse.SC_OK);
        resp.setContentType("application/json;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.write("{\"status\":\"200\",\"msg\":\"权限不够,请联系管理员!\"}");
        out.flush();
        out.close();
    }
}

9,加入 json解析 后的 接受类

public class AuthenticationBean {
    private String userName;
    private String password;
    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;
    }   

}

10,加入权限加载的实现类

**
 * Created by 刘维.
 */
@Configuration
public class MyInvocationSecurityMetadataSourceService implements
        FilterInvocationSecurityMetadataSource {

@Autowired
private PermissionMapper permissionDao;

private HashMap> map = null;


/**
 * 加载权限表中所有权限
 */
public void loadResourceDefine() {
    map = new HashMap<>();
    Collection array;
    ConfigAttribute cfg;
    List permissions = permissionDao.getAllPermissions();
    for (Permission permission : permissions) {
        array = new ArrayList<>();
        if(permission.getCode()!=null){
            cfg = new SecurityConfig(permission.getCode());
            // 此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
            array.add(cfg);
            // 用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
            map.put(permission.getHref(), array);
        }

    }

}

// 此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
@Override
public Collection getAttributes(Object object)throws IllegalArgumentException {
    if (map == null)
        loadResourceDefine();
    // object 中包含用户请求的request 信息
    HttpServletRequest request = ((FilterInvocation) object)
            .getHttpRequest();
    AntPathRequestMatcher matcher;
    String resUrl;
    for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
        resUrl = iter.next();
        matcher = new AntPathRequestMatcher(resUrl);
        if (matcher.matches(request)) {
            return map.get(resUrl);
        }
    }
    return null;
}

@Override
public Collection getAllConfigAttributes() {
    return null;
}

@Override
public boolean supports(Class clazz) {
    return true;
}

}

你可能感兴趣的:(java)